对于重载方法,我遇到了 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));
}
}
最佳答案
在创建模拟对象时,我不会竭尽全力尝试定义一些通用的默认行为。您有两种不同的方法,并且可以明确指定两种不同的行为:
@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
方法等。
关于java - mockito.AdditionalAnswers.returnsFirstArg() 用于重载方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47691364/