【问题标题】:Create a mocked list with objects创建一个包含对象的模拟列表
【发布时间】:2020-02-16 17:33:58
【问题描述】:

我想创建一个带有测试模拟对象的 JUnit 测试:

public class BinCountryCheckFilterImplTest {

    private RiskFilterService riskFilterService = null;

    @Before
    public void beforeEachTest() {

        List<RiskFilters> list = new ArrayList<RiskFilters>();

        riskFilterService = Mockito.mock(RiskFilterService.class);

        // put here list of List<RiskFilters> and return it 
    }

    @Test
    public void testBinCountryCheckFilterImpl() {

        List<RiskFilters> filter_list = riskFilterService.findRiskFiltersByTerminalIdAndType(11, "test");
         // do something                
    }    
}

当RiskFilterService 被调用时,我如何返回列表List&lt;RiskFilters&gt;?

第二次尝试:

public class BinCountryCheckFilterImplTest {

    private RiskFilterService riskFilterService = null;

    @Mock
    List<RiskFilters> mockList = new ArrayList<RiskFilters>();

    @BeforeClass
    public void beforeEachTest() {

        //if we don't call below, we will get NullPointerException
        MockitoAnnotations.initMocks(this);

        mockList.add(new RiskFilters());

        riskFilterService = Mockito.mock(RiskFilterService.class);
    }

    @Test
    public void testBinCountryCheckFilterImpl() {

        when(riskFilterService.findRiskFiltersByTerminalIdAndType(anyInt(), anyString())).thenReturn(mockList);

        List<RiskFilters> filter_list = riskFilterService.findRiskFiltersByTerminalIdAndType(11, "BinCountryCheckFilter");

    }
}

但我得到了riskFilterService 的 NPE。看起来带有注解@test 的方法是在@BeforeClass 之前调用的。

【问题讨论】:

  • RiskFilterService 是您要测试的课程吗?你想模拟什么方法?
  • 是的,我想模拟来自findRiskFiltersByTerminalIdAndType的结果
  • 类似:Mockito.when(riskFilterService.findRiskFiltersByTerminalIdAndType(anyInt(), anyString()).thenReturn(new ArrayList&lt;RiskFilters&gt;());
  • 我收到The method thenReturn(ArrayList&lt;RiskFilters&gt;) is undefined for the type List&lt;RiskFilters&gt;
  • 你能把你想测试的方法贴出来吗?你使用什么版本的 jUnit?

标签: java junit mocking mockito junit5


【解决方案1】:

当单元测试中需要 List 或任何其他 Collection 时,首先要问自己的问题是:我应该为它创建一个 mock,还是应该创建一个包含 mock 的 List 或 Collection。

当被测试的逻辑没有使用列表,而只是传递列表而不是你可以模拟它。

否则,通常最好不要模拟 List 或 Collection,而是创建一个包含模拟对象的普通对象,因为很难知道 List 或 Collections 的哪些方法需要被存根。使用 for 循环迭代项目时调用哪些方法,在它们上使用迭代器时,在它们上使用流时,...?在编写单元测试时,我经常使用带有模拟参数的 Collections.singletonList 或 Arrays.asList 来初始化列表。

我看到您模拟了列表,然后在设置测试时调用 add 方法向其中添加数据。将数据添加到模拟列表是没有意义的。您可以使用 Mockito.when 在应该返回它的时候返回它,但是您会遇到麻烦,因为您可能需要存根更多方法并且很难知道哪些方法(isEmpty,size,...)。您将数据对象添加到列表可能意味着正在测试的方法不仅传递列表,而且将访问其中的数据。在这种情况下,不要模拟列表,而是模拟您放入其中的数据对象。

【讨论】:

    【解决方案2】:

    您提供的信息非常少。但是让我接通

    你必须有BinCountryCheckFilter 课程。请在您的测试类中初始化它并添加注释@InjectMocks

    @InjectMock
    private BinCountryCheckFilter binCountryCheckFilter;
    

    将riskFilterService = Mockito.mock(RiskFilterService.class);从@BeforeClass中取出并公开。

    但这只会模拟你的课程,不会测试任何东西。您可以测试的一件事是没有拨打电话。见下文

    verify(mockList, times(1)).yourMethodName(); 
    

    或在您的测试或方法之前添加以下内容

    when(riskFilterService.yurMethodName).thenReturn(your Return value);
    

    这样您就可以模拟您想要的数据。 如果需要任何其他澄清,请告诉我。

    我不确定您的 JUnit 版本,但您可以删除

    现在从您的代码中删除@BeforeClass 并

     @Mock
        List<RiskFilters> mockList = new ArrayList<RiskFilters>();
    

    也是。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-28
      相关资源
      最近更新 更多