3 回答
TA贡献1777条经验 获得超10个赞
如前所述,不要尝试模拟该List对象。
通常也避免为您可以简单地自己创建的对象创建模拟,并尝试将自己限制为仅模拟依赖项。
测试的简化版本可能如下所示:
由于您的测试涵盖的内容比Unit BookService 我决定在这个例子中将其最小化。
您可能希望在针对特定实现的测试中执行所有其他操作。
@Test
public void getBooksByCategory() {
List<Book> empikBestsellers = EmpikBookProvider.prepare5Bestsellers();
List<Book> merlinBestsellers = MerlinBookProvider.prepare5Bestsellers();
BookServiceSource bookServiceSource1 = Mockito.mock(BookServiceSource.class);
Mockito.when(bookServiceSource1.getName()).thenReturn(Bookstore.EMPIK);
Mockito.when(bookServiceSource1.getBooksByCategory(CategoryType.CRIME)).thenReturn(empikBestsellers);
BookServiceSource bookServiceSource2 = Mockito.mock(BookServiceSource.class);
Mockito.when(bookServiceSource2.getName()).thenReturn(Bookstore.MERLIN);
Mockito.when(bookServiceSource2.getBooksByCategory(CategoryType.CRIME)).thenReturn(merlinBestsellers);
List<BookServiceSource> sources = new ArrayList<>();
sources.add(bookServiceSource1);
sources.add(bookServiceSource2);
BookService service = new BookService(sources);
Map<Bookstore, List<Book>> actualMap = service.getBooksByCategory(CategoryType.CRIME);
// compare result
}
TA贡献2012条经验 获得超12个赞
我认为您不应该嘲笑 BookServiceSource 列表,因为您添加的内容不会执行任何操作,因为它不是真正的列表。
如果可以的话,不应该使用它,它有静默失败的倾向。
我试图提出的另一点是您正在使用模拟列表,因此当它被告知添加元素时它不会。
您可以使用两种解决问题的方法。首先,您可以为 BookServiceSources 流创建 when thenreturn,而不是推荐的解决方案。
其次,更好的方法是创建一个使用 @Before 注释创建 BookService 的 testSetup 方法。
@Before
public void testSetup(){
List<BookServiceSource> list = new LinkedList<>();
list.add(merlinSource);
list.add(empikSource);
bookService = new BookService(list);
}
TA贡献1865条经验 获得超7个赞
尝试@Spy
。它允许您注入您自己初始化的列表的实际实例,也可以部分模拟。
@Spy private List<BookServiceSource> sources = new ArrayList<>();
似乎您为列表使用了不同的名称,更喜欢使用注入模拟字段的 smae 名称;消息来源。
这里有很好的解释。
5. Mockito 中的模拟与间谍:
当 Mockito 创建一个模拟时——它是从一个类型的类中创建的,而不是从一个实际的实例中创建的。模拟只是创建了类的一个基本的 shell 实例,完全用于跟踪与它的交互。
另一方面,间谍将包装现有实例。它仍将以与普通实例相同的方式运行——唯一的区别是它还将被检测以跟踪与其进行的所有交互。
添加回答
举报