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



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

public List<Person> readFile(String filename) {
List<Person> list = new ArrayList<Person>();
JSONParser parser = new JSONParser();
int count = 0;
try {
Object obj = parser.parse(new FileReader(
filename));
JSONObject jsonObject = (JSONObject) obj;
JSONArray array = (JSONArray) jsonObject.get("people");
//System.out.println("Debug: " + array.size());
if(array != null) {
while (count < array.size()) {
Person person = new Person();
JSONObject people = (JSONObject) array.get(count);
person.setName((String) people.get("name"));
Long age = (Long) people.get("age");
person.setAge(Integer.valueOf(age.intValue()));
person.setSex((String) people.get("sex"));
person.setIllness((String) people.get("illness"));
list.add(person);
count++;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}

这会获取一个文件名并返回一个列表,在本例中是一个特定的文件对象列表。这是我迄今为止的测试:

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"));
}
}

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

您还没有模拟要测试的类。即:CCD_ 1。您应该在测试类的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中的mocking:https://dzone.com/articles/getting-started-mocking-java

通常,模拟对象的原因是,它们是您尝试测试的东西所必需的依赖项,模拟它们简化了生成真实对象的过程,并为您提供了一种控制期望和检查交互的方法。

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

  • 正在读取的文件名
  • 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,您将针对真实数据进行测试,这是对代码的一个更现实的测试,而且设置起来也更容易——但您将数据保存在一个单独的文件中,因此它将从测试中删除。

使用选项2,您的测试用例在代码中清晰地列出,使其更易于读取和更新,但它有点冗长,因为您必须伪造代码中的所有样本数据。

你选择哪个选项主要取决于风格和适合你的选项,但我个人可能更喜欢mockedYourClass = mock(YourClass.class);0选项。

希望能有所帮助!

最新更新