如何使用mockito模拟构建器

问题描述 投票:0回答:3

我有一个建筑商:

class Builder{
     private String name;
     private String address;
     public Builder setName(String name){
         this.name = name;
         return this;
    }
     public Builder setAddress(String address){
         this.address = address;
         return this;
    }

}

在mockito中模拟构建器将为每个方法提供null。那么有没有一种简单的方法可以让构建器在每次函数调用时返回自身,而无需使用

when().thenReturn
来模拟每个函数本身。

java unit-testing mockito
3个回答
57
投票

使用 RETURN_DEEP_STUBS 的问题是每次调用方法时都会得到不同的模拟。 我认为从你的问题来看,你想要使用一个默认答案,对于每个具有正确返回类型的方法,它实际上返回调用它的模拟。 这可能类似于以下内容。 请注意,我还没有对此进行测试,因此它可能包含拼写错误,但我希望无论如何其意图都是明确的。

import static org.mockito.Mockito.RETURNS_DEFAULTS;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public class SelfReturningAnswer implements Answer<Object> {

    public Object answer(InvocationOnMock invocation) throws Throwable {
        Object mock = invocation.getMock();
        if(invocation.getMethod().getReturnType().isInstance(mock)){
            return mock;
        }
        return RETURNS_DEFAULTS.answer(invocation);
    }
}

然后,当您创建模拟时,请将其指定为默认答案。 这将使您的模拟从它可以的每个方法中返回自身;但是当你调用一个返回类型对于模拟来说是错误的方法时,它的行为就像一个普通的模拟。

像这样创建你的模拟

Builder mockBuilder = mock( Builder.class, new SelfReturningAnswer());

或者为此类创建一个常量并编写类似的内容

@Mock(answer = SELF_RETURNING) private Builder mockBuilder;

希望有帮助。


48
投票

从 Mockito 2.0(测试版)开始,

RETURNS_SELF
有一个新的默认答案,其行为几乎与 David Wallace 的答案相同。 Mockito 文档中的示例:

@Test
public void use_full_builder_with_terminating_method() {
    HttpBuilder builder = mock(HttpBuilder.class, RETURNS_SELF);
    HttpRequesterWithHeaders requester = new HttpRequesterWithHeaders(builder);
    String response = "StatusCode: 200";

    when(builder.request()).thenReturn(response);

    assertThat(requester.request("URI")).isEqualTo(response);
}

请注意,它同时出现在

Mockito
类和
Answers
枚举上,因此它也与
@Mock(answer = RETURNS_SELF)
语法兼容。


24
投票

您可以使用 RETURN_DEEP_STUBS 来模拟链接 API。

如果您知道构建器被调用的确切顺序,这里有一个如何使用它的示例:

Builder b = Mockito.mock(Builder.class, RETURNS_DEEP_STUBS);
when(b.setName("a name").setAddress("an address")).thenReturn(b);
assert b.setName("a name").setAddress("an address") == b; // this passes

不幸的是,这不会为您提供一种模拟“所有各种构建器方法”的通用方法,以便它们始终返回此值,请参阅另一个答案,您需要这个。

© www.soinside.com 2019 - 2024. All rights reserved.