Подтвердить что ты не робот

Как насмехаться с разработчиком с mockito

У меня есть строитель:

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.

4b9b3361

Ответ 1

Вы можете использовать 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

К сожалению, это не даст вам общий способ издеваться над "всеми различными методами построения", чтобы они всегда возвращали это, см. другой ответ: вам это нужно.

Ответ 2

Проблема с использованием 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;
        }
        else{
            return RETURNS_DEFAULTS.answer(invocation);
        }
    }
}

Затем, когда вы создаете свой макет, укажите это как ответ по умолчанию. Это заставит ваш макет возвращаться от каждого метода, который он может; но он будет вести себя как обычный макет, когда вы вызываете метод, тип возврата которого неверен для макета.

Создайте свой макет, подобный этому

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

или создать константу для этого класса и написать что-то вроде

@Mock( answer = SELF_RETURNING ) private Builder mockBuilder;

Надеюсь, что это поможет.

Ответ 3

Как и в случае с Mockito 2.0 (бета), для RETURNS_SELF существует новый ответ по умолчанию, который ведет себя почти идентично Ответ Дэвида Уоллеса. Пример из документов 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).