java - mockito.AdditionalAnswers.returnsFirstArg() 用于重载方法

标签 java junit mockito

对于重载方法,我遇到了 returnsFirstArg 问题,其中 firstArg 的类型不一定与返回类型相同。

  1. 我希望这两种方法都返回第一个参数的字符串值。
  2. 更好的是,它们总是返回 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/

相关文章:

java - 数组长度不同,Junit 中预期长度 = 1 实际长度 = 0

java - MockitoAnnotations.Mock 类型已弃用

java - Mockito 不 mock

java - 如何使用日历 API 获取 ISO 星期几

java - 使用maven和jenkins,如何测试程序员做了一些测试用例?

java - Web 应用程序似乎启动了一个名为的线程,但未能停止它。这很可能造成内存泄漏

java - Spring 中的事务原子性

ios - Jenkins - 失败 : No test report files were found. 配置错误?

java - 为什么 junit 说我的 boolean 测试应该无效?

android - Mockito 不适用于 androidTest