【问题标题】:Using mokito.when for method with String and Class<T> arguments将 mockito.when 用于带有 String 和 Class<T> 参数的方法
【发布时间】:2020-12-05 20:01:39
【问题描述】:

我有一个方法,我想创建一些单元测试(这个方法变形

applicationContext.getEnvironment().getProperty(key, class)

用于领事集成)

长话短说:

public class DynamicProperties {

 public <T> T getEnvironmentProperty(String key, Class<T> cls) {
        return cls.cast(applicationContext.getEnvironment().getProperty(key,cls));
    }
}

在测试其他使用 DynamicProperties 类的类时,如下:

   @Test
    void testA() {
        //before
        when(dynamicProperties.getEnvironmentProperty(eq(KEY_A), Boolean.class)).thenReturn(true);
        when(dynamicProperties.getEnvironmentProperty(eq(KEY_B), Long.class)).thenReturn(0l);

        //when
        archivedSensorsService.testMethod();

        //than
        verify(...)
    }

KEY_A KEY_B 是公共静态最终字符串 我收到以下错误:

This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

尝试以下操作时:

 @Test
        void testA() {
            //before
            when(dynamicProperties.getEnvironmentProperty(eq(KEY_A), anyObject())).thenReturn(true);
            when(dynamicProperties.getEnvironmentProperty(eq(KEY_B), anyObject())).thenReturn(0l);
    
            //when
            archivedSensorsService.testMethod();
    
            //than
            verify(...)
        }

得到以下错误:

org.mockito.exceptions.misusing.PotentialStubbingProblem: 
Strict stubbing argument mismatch. Please check:
 - this invocation of 'getEnvironmentProperty' method:
    dynamicProperties.getEnvironmentProperty(
    null,
    null
);
    -> at com.xxx.xxx ionNotBeenTriggered(..)
 - has following stubbing(s) with different arguments:
    1. dynamicProperties.getEnvironmentProperty(
    null,
    null
);

有什么建议吗?

【问题讨论】:

    标签: java unit-testing mocking spring-boot-test


    【解决方案1】:

    这个问题是由混合使用和不使用参数匹配器的模拟引起的。如果您对模拟方法参数之一使用参数匹配器,则必须对所有这些参数使用匹配器。你可以阅读更多here

    我已经创建了一个简单的project on GitHub 和一个解决方案 - 如果你愿意,可以查看它,但这里是 sn-p:

    @Test
    void withoutEq() {
        DynamicProperties dynamicProperties = mock(DynamicProperties.class);
        when(dynamicProperties.getEnvironmentProperty(KEY_A, Boolean.class))
                .thenReturn(true);
        when(dynamicProperties.getEnvironmentProperty(KEY_B, Long.class))
                .thenReturn(1L);
    
        assertAll(
                () -> assertTrue(dynamicProperties.getEnvironmentProperty(KEY_A, Boolean.class)),
                () -> assertEquals(1, dynamicProperties.getEnvironmentProperty(KEY_B, Long.class))
        );
    }
    
    @Test
    void withEq() {
        DynamicProperties dynamicProperties = mock(DynamicProperties.class);
        when(dynamicProperties.getEnvironmentProperty(eq(KEY_A), eq(Boolean.class)))
                .thenReturn(true);
        when(dynamicProperties.getEnvironmentProperty(eq(KEY_B), eq(Long.class)))
                .thenReturn(1L);
    
        assertAll(
                () -> assertTrue(dynamicProperties.getEnvironmentProperty(KEY_A, Boolean.class)),
                () -> assertEquals(1, dynamicProperties.getEnvironmentProperty(KEY_B, Long.class))
        );
    }
    

    如您所见 - 其中一种方法对方法的两个参数都使用 eq 匹配器,而另一种则不使用任何参数。两项测试均通过。

    你的情况

    when(dynamicProperties.getEnvironmentProperty(eq(KEY_A), anyObject())).thenReturn(true);
    

    这个模拟没有导致“匹配器与原始值结合”错误,因为eqanyObject 都是参数匹配器,但是

    when(dynamicProperties.getEnvironmentProperty(eq(KEY_A), Boolean.class)).thenReturn(true);
    

    有一个匹配器 (eq) 和一个简单对象 (Boolean.class 没有 eq)。

    【讨论】:

    • 嗯...不确定,我完全明白了,我使用了带有anyObject()的那个,我仍然收到我在帖子中写的错误,你能澄清一下吗?
    • 这是由于使用参数匹配器多次模拟造成的,如果启用了严格的存根,则实际上返回 null(这就是 Mockito 的实现方式)。您可以阅读更多here,但基本上为了避免此错误,您应该改用doReturn(...).when(...)(如链接文档中所述)。
    猜你喜欢
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多