英文:
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 <T> T getEnvironmentProperty(String key, Class<T> 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(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
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 'getEnvironmentProperty' method:
dynamicProperties.getEnvironmentProperty(
null,
null
);
-> 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);
这个模拟没有引发“匹配器与原始值混合使用”的错误,因为eq
和anyObject
都是参数匹配器,但是:
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(
() -> 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))
);
}
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
).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论