使用 `mokito.when` 处理带有字符串和 `Class` 参数的方法

huangapple go评论79阅读模式
英文:

Using mokito.when for method with String and Class<T> arguments

问题

以下是翻译好的内容:

我有一个方法,我想为其创建一些单元测试(此方法用于包装

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

用于Consul集成)

长话短说:

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

    //then
    verify(...)
}

KEY_A和KEY_B是公共的静态final字符串。我遇到了以下错误:

这个异常可能发生在匹配器与原始值组合的情况下:
//不正确的写法:
someMethod(anyObject(), "原始字符串");
使用匹配器时,所有参数都必须由匹配器提供。
例如:
//正确的写法:
someMethod(anyObject(), eq("匹配器字符串"));

尝试以下写法时:

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

    //then
    verify(...)
}

遇到以下错误:

org.mockito.exceptions.misusing.PotentialStubbingProblem: 
严格的存根参数不匹配。请检查:
- 'getEnvironmentProperty' 方法的此次调用:
  dynamicProperties.getEnvironmentProperty(
  null,
  null
);
  -> at com.xxx.xxx ionNotBeenTriggered(..)
- 具有不同参数的以下存根:
  1. dynamicProperties.getEnvironmentProperty(
  null,
  null
);

有什么建议吗?

英文:

I have a method which I would like to create some unit test (this method warping

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

for consul integration)

Long story short:

public class DynamicProperties {

 public &lt;T&gt; T getEnvironmentProperty(String key, Class&lt;T&gt; cls) {
        return cls.cast(applicationContext.getEnvironment().getProperty(key,cls));
    }
}

when testing some other class which using the DynamicProperties class, as the following:

   @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 are public static final strings
I'm getting the following error:

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

When trying the following:

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

Getting the following error:

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

Any suggestions?

答案1

得分: 2

问题是由于混合使用了带有参数匹配器和不带参数匹配器的模拟造成的。如果你对模拟方法的其中一个参数使用了参数匹配器,那么你必须对所有参数使用匹配器。你可以在这里阅读更多信息1

我已经在GitHub上创建了一个简单的项目,其中包含了一个解决方案 - 你可以查看一下,但以下是代码片段:

@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)。

英文:

The problem is caused by mixing mocking with and without argument matchers. If you use an argument matcher to one of the mocked method arguments, you have to use a matcher for all of them. You can read more here.

I've created a simple project on GitHub with a solution - you can check it if you like, but here's the snippet:

@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(
            () -&gt; assertTrue(dynamicProperties.getEnvironmentProperty(KEY_A, Boolean.class)),
            () -&gt; 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(
            () -&gt; assertTrue(dynamicProperties.getEnvironmentProperty(KEY_A, Boolean.class)),
            () -&gt; assertEquals(1, dynamicProperties.getEnvironmentProperty(KEY_B, Long.class))
    );
}

As you can see - one of the methods uses eq matcher for both of the method's arguments and the other one uses none. Both tests pass.

In your case

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

this mock did not cause "matcher combined with raw values" error, because eq and anyObject are both argument matchers, but

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

has a matcher (eq) and a simple object (Boolean.class without eq).

huangapple
  • 本文由 发表于 2020年8月16日 22:27:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/63438057.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定