Исключение: mockito хотел, но не был вызван, на самом деле было нулевое взаимодействие с этим макетом

У меня есть интерфейс

Interface MyInterface {
  myMethodToBeVerified (String, String);
}

И реализация интерфейса

class MyClassToBeTested implements MyInterface {
   myMethodToBeVerified(String, String) {
    …….
   }
}

У меня есть еще один класс

class MyClass {
    MyInterface myObj = new MyClassToBeTested();
    public void abc(){
         myObj.myMethodToBeVerified (new String("a"), new String("b"));
    }

}

Я пытаюсь написать JUnit для MyClass. Я сделал

class MyClassTest {
    MyClass myClass = new MyClass();

    @Mock
    MyInterface myInterface;

    testAbc(){
         myClass.abc();
         verify(myInterface).myMethodToBeVerified(new String("a"), new String("b"));
    }
}

Но я получаю mockito, но не вызывается, на самом деле было нулевое взаимодействие с этим макетом при проверке вызова.

может кто-нибудь предложить некоторые решения.

Ответ 1

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

void testAbc(){
     myClass.myObj = myInteface;
     myClass.abc();
     verify(myInterface).myMethodToBeVerified(new String("a"), new String("b"));
}

хотя было бы разумнее выбрать весь код инициализации в @Before

@Before
void setUp(){
     myClass = new myClass();
     myClass.myObj = myInteface;
}

@Test
void testAbc(){
     myClass.abc();
     verify(myInterface).myMethodToBeVerified(new String("a"), new String("b"));
}

Ответ 2

Ваш класс MyClass создает новый MyClassToBeTested вместо использования вашего макета. Моя статья о вики Mockito описывает два способа борьбы с этим.

Ответ 3

@Ответ Jk1 - это хорошо, но Mockito также позволяет более сжатую инъекцию с помощью аннотаций:

@InjectMocks MyClass myClass; //@InjectMocks automatically instantiates too
@Mock MyInterface myInterface

Но независимо от того, какой метод вы используете, аннотации не обрабатываются (даже не ваш @Mock), если вы каким-то образом не вызываете статический MockitoAnnotation.initMocks() или не комментируете класс с помощью @RunWith(MockitoJUnitRunner.class).

Ответ 4

@jk1 ответ прекрасен, так как @igor Ganapolsky спросил, почему мы не можем использовать Mockito.mock здесь? я пишу этот ответ.

Для этого мы предоставляем один метод setter для myobj и устанавливаем значение myobj с помощью mocked object.

class MyClass {
    MyInterface myObj;

    public void abc() {
        myObj.myMethodToBeVerified (new String("a"), new String("b"));
    }

    public void setMyObj(MyInterface obj)
    {
        this.myObj=obj;
    }
}

В нашем тестовом классе мы должны написать ниже код

class MyClassTest {

MyClass myClass = new MyClass();

    @Mock
    MyInterface myInterface;

    @test
    testAbc() {
        myclass.setMyObj(myInterface); //it is good to have in @before method
        myClass.abc();
        verify(myInterface).myMethodToBeVerified(new String("a"), new String("b"));
     }
}