Имитация вызова метода из другого класса

Моя структура кода:

class A {
    void methodA() {
        //some code
        B b = new B();
        response = b.methodB(arg1, arg2);
        //some code using "response"
    }
}

Я являюсь UNIT-тестирующим классом A и не хочу на самом деле вызывать methodB (). Есть ли способ имитировать вызов этого метода с помощью настраиваемого ответа. Я попробовал Mockito издеваться над вызовом этого метода, как показано ниже:

B classBMock = Mockito.mock(B.class);
Mockito.when(classBMock.methodB(arg1, arg2)).thenReturn(customResponse);
A objA = new A();
objA.methodA();

При вызове метода methodA () указанным выше способом я не получаю customResponse, когда methodB () вызывается внутри A. Но когда я вызываю methodB () с помощью classBMock, я получаю customResponse. Есть ли способ получить customResponse от methodB () при вызове methodA ().


person Ash    schedule 08.05.2015    source источник


Ответы (1)


Один из распространенных способов сделать это - извлечь создание экземпляра соавтора в метод и spy выделить класс, который вы хотите протестировать.

В этом случае вы можете переписать A следующим образом:

public class A {
    public B createB() {
        return new B();
    }

    public void methodA() {
        //some code
        B b = createB();
        response = b.methodB(arg1, arg2);
       //some code using "response"
    }
}

Теперь ваш тест может spy тестировать A экземпляр и внедрить имитацию для B:

B classBMock = Mockito.mock(B.class);
Mockito.when(classBMock.methodB(arg1, arg2)).thenReturn(customResponse);
A objA = Mockito.spy(new A());
Mockito.when(objA.createB()).thenReturn(classBMock());
objA.methodA();


Изменить:
Если вы не можете изменить A, можно воспользоваться другим способом: PowerMock. Обратите внимание, что этот фрагмент кода показывает только релевантные насмешки и не отображает аннотации, необходимые для того, чтобы PowerMock мог инструментировать ваш класс:

B classBMock = Mockito.mock(B.class);
Mockito.when(classBMock.methodB(arg1, arg2)).thenReturn(customResponse);
PowerMockito.whenNew(B.class).withNoArguments().thenReturn(classBMock);
A objA = new A();
objA.methodA();
person Mureinik    schedule 08.05.2015
comment
Спасибо @Mureinik. Это возможное решение, но поскольку я не могу изменить исходный исходный код, есть ли способ сделать это без каких-либо изменений кода? - person Ash; 08.05.2015
comment
@ user2393393 Один из вариантов - PowerMock, хотя лично я не фанат. Подробнее см. Мой отредактированный ответ. - person Mureinik; 08.05.2015
comment
Спасибо @Mureinik. Это служит цели. Есть ли причина, по которой вы не предпочтете PowerMock? Просто спрашиваю, нужно ли мне что-то знать. - person Ash; 08.05.2015
comment
@ user2393393 PowerMock использует инструментарий байт-кода, который обычно оказывает значительное влияние на производительность ваших тестов и может быть изворотливым, если ваш код не является прямым и включает отражение или другие методы манипулирования байтовым кодом. - person Mureinik; 08.05.2015
comment
Это было полезно. Спасибо. - person Ash; 08.05.2015