模拟特定的类对象存根失败的测试mockito

时间:2017-10-28 19:49:24

标签: java junit nullpointerexception mockito

我正在读一个填充我的类对象的json对象,所以我在嘲笑我的类对象,不知道哪种方式是最好的方法。这是我的方法:

package pricing;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.BeforeClass;
import org.junit.Test;

import com.pricing.DiscountPricing;
import com.pricing.model.Person;

 @SuppressWarnings("deprecation")
public class DiscountPricingTest {

private static DiscountPricing mockDPclass;
private static Person mockPerson1;
private static Person mockPerson2;
private static Person mockPerson3;

@BeforeClass
public static void setUp() {
    mockDPclass = mock(DiscountPricing.class);
    mockPerson1 = new Person(50, "Allergies", "Kelly", "female");
    mockPerson2 = new Person(40, "Sleep Apnea", "Josh", "male");
    mockPerson3 = new Person(20, "Heart Disease", "Brad", "male");
}

@Test
public void readFileTest() {
    String filename = "Consumers.json";
    DiscountPricing dpclass = new DiscountPricing();
    List<Person> allPeople = dpclass.readFile(filename);
    List<Person> mockPeople = new ArrayList<Person>();
    mockPeople.add(mockPerson1);
    mockPeople.add(mockPerson2);
    mockPeople.add(mockPerson3);
    assertEquals(mockPeople.size(), allPeople.size());
    assertTrue(allPeople.get(0).getName().equals("Kelly"));
}
}

这需要一个文件名并返回一个列表,在本例中是一个特定的文件对象列表。到目前为止,这是我的测试:

Msbuild

看看我对Mockito使用嘲讽是否正确?

2 个答案:

答案 0 :(得分:1)

你没有嘲笑你要测试的课程。即:mockedYourClass = mock(YourClass.class);。您应该在测试类的setUp()方法中执行此操作。

此外,在测试之前,您不会使用模拟数据来存储模拟类的方法,即: when(mockDPclass.readFile("Consumers.json")).thenReturn(Arrays.asList(mockPerson1, mockPerson2, mockPerson3));你应该把它放在setUp()方法的末尾。

在readFileTest()方法中,您可以执行以下操作:

List<Person> persons = mockDPclass.readFile("Consumers.json");
assertEquals(3, persons.size());
Person person = persons.get(0);
assertEquals("Kelly", person.getName());

这是一个很好的教程,如何开始使用java进行模拟:https://dzone.com/articles/getting-started-mocking-java

答案 1 :(得分:1)

通常,模拟对象的原因是因为它们是您要测试的东西的必需依赖项,并且模拟它们可以简化制作真实对象并为您提供控制期望和检查交互的方法。

在您的情况下,您正在测试一个函数来验证它是否正确地从文件中读取数据。您的依赖项是:

  • 您正在阅读的文件名
  • 解析方法中JSONParser实例new
  • 您在方法中FileReader new实例读取文件

鉴于此,你可以做两件事:

1)创建包含您要测试的测试数据的假文件。然后你的测试看起来像这样。

@Test
public void readFileTest() {
    DiscountPricing dp = new DiscountPricing();
    List<Person> emptyList = dp.readFile("test_file_empty.json");
    assertThat(emptyList, is(empty()));

    List<Person> singleItemList = dp.readFile("test_file_single.json");
    assertThat(singleItemList, hasSize(1));
    // TODO: Assert state of Person at singleItemList(0) is correct

    List<Person> multiItemList = dp.readFile("test_file_multi.json");
    assertThat(mutilItemList, hasSize(2));
    // TODO: Assert state of each person in list is correct
}

2)允许注入你需要的JSONParser,这样你就可以模拟它并提供虚拟数据来进行测试。

@Test
public void readFileTest() {
    JSONParser mockParser = mock(JSONParser.class);
    DiscountPricing dp = new DiscountPricing();
    dp.setJSONParser(mockParser); // Parser is now a field in DiscountPricing you use in the readFile method

    JSONObject emptyObject = new JSONObject();
    when(mockParser.parse(any(FileReader.class))).thenReturn(emptyObject);
    List<Person> emptyList = dp.readFile("this doesn't matter");
    assertThat(emptyList, is(empty()));

    JSONObject singleObject = new JSONObject();
    // TODO: Populate singleObject with fake fields
    when(mockParser.parse(any(FileReader.class))).thenReturn(singleObject);
    List<Person> singleItemList = dp.readFile("this doesn't matter");
    assertThat(singleItemList, hasSize(1));
    // TODO: Assert state of Person at singleItemList(0) is correct

    JSONObject multiObject = new JSONObject();
    // TODO: Populate multiObject with fake fields
    when(mockParser.parse(any(FileReader.class))).thenReturn(multiObject);
    List<Person> multiItemList = dp.readFile("this doesn't matter");
    assertThat(mutilItemList, hasSize(2));
    // TODO: Assert state of each person in list is correct
}

使用选项1进行实际数据测试,对代码进行更实际的测试,并且设置起来更容易 - 但是您将数据放在单独的文件中,以便从测试中删除。 / p>

使用选项2,您可以在代码中清楚地显示测试用例,使其更易于阅读和更新,但由于您必须伪造代码中的所有示例数据,因此更加冗长。

你选择哪个选项主要取决于风格和适合你的选项,但我个人可能更喜欢选项1

希望有所帮助!