简体   繁体   English

如何在同一个 Mock 上获得两个方法调用以返回不同的值?

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

I have a function that I am trying to mock that contains recursive logic in the form of a while loop and i'm trying to figure out how to access the inner part of the while loop without looping forever.我有一个我试图模拟的函数,它包含 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);
    }
}

I am able to write a junit test to verify that the while loop is never entered if the grocery list is empty.我能够编写一个 junit 测试来验证如果购物清单为空,则永远不会进入 while 循环。 However, i'm not sure how to write code to test that the while loop is entered because I need to mock groceryListDao.getList to not be empty to enter the while loop and then empty to exit the while loop.但是,我不确定如何编写代码来测试是否进入了 while 循环,因为我需要模拟杂货清单 Dao.getList 不为空以进入 while 循环,然后为空以退出 while 循环。 I don't know how to do both.我不知道如何做到这两点。

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

How do I verify that total() is being called inside the loop without getting stuck?如何验证是否在循环内调用了 total() 而不会卡住?

You can chain thenReturn , so that subsequent calls to the mock return different things:您可以链接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();
    }
}

This is not a perfect test, as the mock would return an empty list without an intervening call to total .这不是一个完美的测试,因为模拟将返回一个空列表,而没有对total的干预调用。

You can simulate the semantics of your DAO like this:您可以像这样模拟 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();
    }
}

For completeness, here's the GroceryService code:为了完整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.

相关问题 如何在对模拟的不同调用中返回不同的值? - How do I return different values on different calls to a mock? 我在同一行中有两个方法调用需要模拟,如何模拟呢? - I have two method calls in same line which I need to mock.How to mock it? 如何使用Mockito测试对同一方法的两个不同调用,每个调用返回不同的响应? - How can I use Mockito to test two different calls to the same method that returns a different response for each call? 如何模拟 bean 的某些方法调用,但在同一测试类的其他方法调用中使用已定义的 bean? - How can I mock some method calls of a bean but use the defined bean in other method calls in the same test class? 如何以相同的方法返回不同的对象? - How can i return different objects in same method? Mockito 使用不同的集合参数模拟相同的方法调用 - Mockito mock same method calls with different collection-arguments 如何设置Mockito模拟以对多个不同的方法调用使用相同的答案 - How to set up Mockito mock to use same answer for multiple different method calls 如何使mocked方法返回相同的mock - How to make a mocked method return the same mock 我如何在同一个 class 的不同方法中使用私有 static 方法(对象的扩展)的返回值? (爪哇) - How can i use the return value of a private static method (extension of object) in a different method in that same class? (java) 如何模拟一个方法来调用同一类中存在的其他方法 - How to mock a method that calls other methods that are present in the same class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM