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

Ложные вложенные вызовы методов с использованием mockito

У меня есть 4 класса, которые позволяют говорить A, B, C, D каждый вызов методов из другого.

теперь я издевался над классом A и хочу издеваться над методом, использующим mockito

A a = Mockito.mock(A.class);

и хотите получить "foo" для рекурсивных вызовов методов, таких как

a.getB().getC().getD() должен возвращать "foo"

Я пробовал

когда (a.getB() ЕОКП() GETD()..) ThenReturn ( "Foo" );.

но получил nullPointerException

тогда я попробовал

doReturn ( "Foo" ), когда (a.getB() ЕОКП() GETD()..);.

тогда я получил org.mockito.exceptions.misusing.UnfinishedStubbingException:

Я знаю, что могу создавать объекты B, C и D или даже писать что-то вроде

B b = mock (B.class) или A.setB(новый B())

и т.д.

Но разве я не могу сделать это за один выстрел? Любая помощь будет оценена.

4b9b3361

Ответ 1

Из комментариев:

Добавление RETURNS_DEEP_STUBS выполнило трюк:

A a = Mockito.mock(A.class, Mockito.RETURNS_DEEP_STUBS);

Ответ 2

Технический ответ Abhijeet технически правильный, но важно понять: вы должны не делать это.

Ваш "производственный" код сильно нарушает Закон Деметры: ваш класс A должен не знают, что он должен получить B, чтобы получить C, чтобы получить D.

Это просто приводит к супер-жесткой связи между всеми этими классами. Не очень хорошая идея.

В этом смысле: вы должны увидеть тот факт, что вам нужно делать особые вещи здесь, чтобы получить ваш тестовый процесс, на самом деле является показателем того, что ваш производственный код делает вне нормального.

Итак, вместо "исправления" вашей тестовой установки рассмотрите проблему реальной. И это дизайн вашего производственного кода!

И для записи: getB(). getC(). getD() не является "рекурсивным" вызовом; это скорее "плавная" цепочка вызовов методов. И как сказано: это не хорошая вещь.

Ответ 3

Попробуйте создать макет каждого из вложенных объектов, а затем смоделируйте отдельный метод, вызываемый каждым из этих объектов.

Если целевой код похож на:

public Class MyTargetClass {

    public String getMyState(MyClass abc){

       return abc.getCountry().getState();
    }
}

Затем, чтобы проверить эту строку, мы можем создать макеты каждого из отдельных вложенных объектов, как показано ниже:

public Class MyTestCase{

@Mock
private MyTargetClass myTargetClassMock;

@Mock
private MyClass myclassMockObj;

@Mock
private Country countryMockObj;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

    @Test
    public void test01(){

       when(myclassMockObj.getCountry()).thenReturn(countryMockObj);
       when(countryMockObj.getState()).thenReturn("MY_TEST_STATE");
       Assert.assertEquals("MY_TEST_STATE", myTargetClassMock.getMyState(myclassMockObj));
    }
}