Mockito returnFirstArg()使用

Gep*_*Gep 6 java mockito java-8

我开始使用Mockito了AdditionalAnswers#returnsFirstArg,这很棒:

when(myMock.myFunction(anyString())).then(returnsFirstArg());
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有一种简单的方法来提取输入参数,以便在例如构造函数中使用:

when(myMock.myFunction(anyString())).thenReturn(new MyObject((String)returnsFirstArg()));
Run Code Online (Sandbox Code Playgroud)

(这显然不起作用......)

Mur*_*nik 6

最简单的(唯一的?)方法是IMHO,它将使用该thenAnswer方法,它不仅可以返回值,还可以实际执行某些代码.Java 8使这个特别优雅,因为您可以使用匿名lambda:

when(myMock.myFunction(anyString()))
    .thenAnswer(i -> new MyObject((String)i.getArguments()[0]);
Run Code Online (Sandbox Code Playgroud)


hol*_*ava 5

我想你可能需要一个辅助类AnswerPipeline,我稍后会介绍它如何使测试更具可读性、更具表现力和更有趣!!!

注意:您可以通过方法将 any 转换Answer为,而不仅仅是.AnswerPipelineAnswerPipeline#will(Answer)returnsFirstArg()

THEN使用语法糖来描述测试,例如:

Function<String, String> function = mock(Function.class);

when(function.apply(anyString())).then(
    /**/ will(returnsFirstArg()) // adapt an Answer to an AnswerPipeline
    /**/.as(String.class)  // set the result type
    /**/.to(String::toUpperCase) // transforming the result
);

assertThat(function.apply("first"), equalTo("FIRST"));
Run Code Online (Sandbox Code Playgroud)

那么容易,没有困难解决您的问题:

when(myMock.myFunction(anyString()))
           .then(will(returnsFirstArg()).as(String.class).to(MyObject::new));
Run Code Online (Sandbox Code Playgroud)

AnswerPipeline 类

interface AnswerPipeline<T> extends Answer<T> {

    static <R> AnswerPipeline<R> will(Answer<R> answer) {
        return answer::answer;
    }

    default <R> AnswerPipeline<R> as(Class<R> type) {
        return to(type::cast);
    }

    default <R> AnswerPipeline<R> to(Function<T, R> mapper) {
        return it -> mapper.apply(answer(it));
    }
}
Run Code Online (Sandbox Code Playgroud)