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 實例,完全用于跟蹤與它的交互。
另一方面,間諜將包裝現有實例。它仍將以與普通實例相同的方式運行——唯一的區別是它還將被檢測以跟蹤與其進行的所有交互。
添加回答
舉報