我遇到returnsFirstArg
重载方法的问题,其中firstArg
与返回类型的类型不同。
key
无论如何要实现这一目标并让这些测试成为绿色吗?
这是一个最低限度的非工作示例,在实时翻译中更复杂,无法修改。
package test;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.mock;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import java.util.Locale;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class TranslatorTest {
private class Translator {
String getText(final String key) {
return "translated " + key;
}
String getText(final Locale locale, final String key) {
return "translated " + key + " for locale " + locale;
}
}
@Test
public void test_withoutToString() throws Exception {
final String key = "com.stackoverflow.translator.label";
Translator translator = mock(Translator.class, returnsFirstArg());
assertThat(translator.getText(key), is(key));
final Locale locale = new Locale("en_GB"); // java.lang.ClassCastException: java.util.Locale cannot be cast to java.lang.String
assertThat(translator.getText(locale, key), is(key));
}
@Test
public void test_withToString() throws Exception {
final String key = "com.stackoverflow.translator.label";
Translator translator = mock(Translator.class, returnsFirstArg().toString());
assertThat(translator.getText(key), is(key));
/*
* java.lang.AssertionError:
* Expected: is "com.stackoverflow.translator.label"
* but: was null
*/
final Locale locale = new Locale("en_GB");
assertThat(translator.getText(locale, key), is(key));
}
}
答案 0 :(得分:2)
在创建模拟对象时,我不会向后弯曲以尝试定义一些通用的默认行为。您有两种不同的方法,可以明确指定两种不同的行为:
@Before
public void setUp() {
translator = mock(Translator.class);
when(translator.getText(any(), any()))
.thenAnswer(AdditionalAnswers.returnsSecondArg());
when(translator.getText(any()))
.thenAnswer(AdditionalAnswers.returnsFirstArg());
}
修改:
强>
解决评论中添加/澄清的要求可能会有问题,除非您有一个很好的方法来识别您想要返回的参数。
假设您可以使用一些直接逻辑,比如返回第一个字符串参数,您可以实现自己的Answer
:
Answer<Object> returnsFirstString =
invocationOnMock -> Arrays.stream(invocationOnMock.getArguments())
.filter(String.class::isInstance)
.findFirst()
.orElse(null);
translator = mock(Translator.class, returnsFirstString);
当然,这可以通过一些不同的逻辑进行改进,例如仅适用于getText
方法等。