簡體   English   中英

如何在同一個 Mock 上獲得兩個方法調用以返回不同的值?

[英]How can I get two method calls on the same Mock to return different values?

我有一個我試圖模擬的函數,它包含 while 循環形式的遞歸邏輯,我試圖弄清楚如何訪問 while 循環的內部而不是永遠循環。

//this is supposed to go through all the items in the grocery list given the parameters until the groceries are all checked out 
public void checkOut(String maxItems, String code){
    List<cereal> groceryList;
    groceryList = groceryListDao.getList(String maxItems, String code);
    while (!groceryList.isEmpty()){
    groceryListDao.total();
    //other logic
    groceryList = groceryListDao.getList(String maxItems, String code);
    }
}

我能夠編寫一個 junit 測試來驗證如果購物清單為空,則永遠不會進入 while 循環。 但是,我不確定如何編寫代碼來測試是否進入了 while 循環,因為我需要模擬雜貨清單 Dao.getList 不為空以進入 while 循環,然后為空以退出 while 循環。 我不知道如何做到這兩點。

@Test
public void checkout() {
    List<Cereal> cereal = new ArrayList<>();
    Cereal x = new Cereal();
    cereal.add(x);
    when(groceryListDao.getList(anyString(), anyString())).thenReturn(cereal);
    groceryService.checkout("10", "A5ALV350IIXL");
    verify(groceryListDao, times(1).total());
}

如何驗證是否在循環內調用了 total() 而不會卡住?

您可以鏈接thenReturn ,以便對模擬的后續調用返回不同的內容:

public class GroceryServiceTest {
    @Test
    public void checkout() {
        GroceryService.GroceryListDao groceryListDao = mock(GroceryService.GroceryListDao.class);
        GroceryService groceryService = new GroceryService(groceryListDao);
        List<GroceryService.Cereal> cereal = new ArrayList<>();
        GroceryService.Cereal x = new GroceryService.Cereal();
        cereal.add(x);
// first return a list with one item, then an empty list
        when(groceryListDao.getList(anyString(), anyString())).thenReturn(cereal).thenReturn(Collections.emptyList());
        groceryService.checkout("10", "A5ALV350IIXL");
        verify(groceryListDao, times(1)).total();
    }
}

這不是一個完美的測試,因為模擬將返回一個空列表,而沒有對total的干預調用。

您可以像這樣模擬 DAO 的語義:

public class GroceryServiceTest {
    @Test
    public void checkout() {
        GroceryService.GroceryListDao groceryListDao = mock(GroceryService.GroceryListDao.class);
        GroceryService groceryService = new GroceryService(groceryListDao);
        List<GroceryService.Cereal> cereal = new ArrayList<>();
        AtomicBoolean totalCalled = new AtomicBoolean(false);
        GroceryService.Cereal x = new GroceryService.Cereal();
        cereal.add(x);
        when(groceryListDao.getList(anyString(), anyString())).thenAnswer(new Answer<List<GroceryService.Cereal>>() {

            @Override
            public List<GroceryService.Cereal> answer(InvocationOnMock invocationOnMock) throws Throwable {
                if (totalCalled.get()) {
                    return Collections.emptyList();
                } else {
                    return cereal;
                }
            }
        });
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
                totalCalled.set(true);
                return null;
            }
        }).when(groceryListDao).total();
        groceryService.checkout("10", "A5ALV350IIXL");
        verify(groceryListDao, times(1)).total();
    }
}

為了完整GroceryService ,這里是GroceryService代碼:

import java.util.List;

public class GroceryService {
    final GroceryService.GroceryListDao groceryListDao;

    public GroceryService(GroceryService.GroceryListDao groceryListDao) {
        this.groceryListDao = groceryListDao;
    }
    interface GroceryListDao {
        List<Cereal> getList(String maxItems, String code);
        void total();
    }
    static class Cereal {}
    public void checkout(String maxItems, String code){
        List<Cereal> groceryList;
        groceryList = groceryListDao.getList(maxItems, code);
        while (!groceryList.isEmpty()){
            groceryListDao.total();
            //other logic
            groceryList = groceryListDao.getList(maxItems, code);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM