#java #unit-testing #mocking #spring-boot-test
#java #модульное тестирование #издевательство #spring-boot-test
Вопрос:
У меня есть метод, с помощью которого я хотел бы создать некоторый модульный тест (этот метод деформирует
ApplicationContext.getEnvironment().getProperty(ключ, класс)
для интеграции с 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();
//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
);
Есть предложения?
Ответ №1:
Проблема вызвана смешиванием mocking с сопоставителями аргументов и без них. Если вы используете средство сопоставления аргументов с одним из аргументов издевательского метода, вам придется использовать средство сопоставления для всех них. Вы можете прочитать больше здесь.
Я создал простой проект на 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
).
Комментарии:
1. Хм … не уверен, я вас полностью понял, я использовал тот, что с AnyObject (), я все еще получал ошибку, как я написал в сообщении, можете ли вы уточнить это?
2. Это вызвано многократным пересмотром с помощью средств сопоставления аргументов, которые на самом деле возвращают
null
(именно так реализован Mockito), если включено строгое заглушение. Вы можете прочитать больше здесь , но в основном, чтобы избежать этой ошибки, вы должны использоватьdoReturn(...).when(...)
вместо этого (как указано в связанных документах).