【问题标题】:How can I get two method calls on the same Mock to return different values?如何在同一个 Mock 上获得两个方法调用以返回不同的值?
【发布时间】:2021-10-21 22:36:11
【问题描述】:

我有一个我试图模拟的函数,它包含 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循环,因为我需要模拟groceryListDao.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() 而不会卡住?

【问题讨论】:

  • 这不是递归的。 checkOut 不调用自己。这段代码是如何工作的?如果对getList 的第一次调用不是空的,为什么下一个是空的? total 是否停止在进一步调用中返回项目?
  • (也请发布您的实际代码,因为您发布的内容无法编译)
  • 2 种独立的测试方法

标签: java spring junit mockito


【解决方案1】:

您可以链接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 代码:

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

【讨论】:

    猜你喜欢
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    • 2013-05-13
    • 2021-02-18
    • 1970-01-01
    • 2012-01-17
    相关资源
    最近更新 更多