Ошибка Mockito: «Разыскивается, но не вызывается ... фактически с этим макетом не было никаких взаимодействий» - PullRequest
0 голосов
/ 14 апреля 2020

Я получаю вышеуказанную ошибку при выполнении моего модульного теста для класса java в проекте Android (в Android Studio).

Тестируемый класс:

import android.content.Context;
import android.util.Log;

import **.CustomObject;
import java.util.concurrent.CountDownLatch;
import androidx.annotation.NonNull;

public class CustomClass {
  private static final String string = "a";
  private static CustomObject customObject = null;
  private static CountDownLatch initializedLatch = new CountDownLatch(1);

  @NonNull
  public static CustomObject1 getCustomObject1() {
      try {
          initializedLatch.await();
          assert customObject != null;
          return customObject;

      } catch (InterruptedException e) {
        throw new RuntimeException(".");
      }
  }

  public static void methodA(final Context context,
                                         final String string1,
                                         ) throws exception {
      initializedLatch.countDown();
  }


  public static void methodB(@NonNull final CustomObject customObjectInput) {
      customObject = customObjectInput;
  }
}

Класс теста:

import android.content.Context;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.util.concurrent.CountDownLatch;

import **.CustomObject;

import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;

import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;

@RunWith(MockitoJUnitRunner.class)
public class CustomClassTest{

    @Mock
    static CustomObject customObject;

    @Mock
    static Context context;

    @Mock
    CountDownLatch mCountDownLatch;

    @Mock
    CountDownLatch mInitializedLatch;

    @InjectMocks
    CustomClass customClass;

    @Before
    public void setUp() {
        customObject = Mockito.spy(CustomObject.class);
        context = Mockito.spy(Context.class);
    }

    @Test
    public void customClassTest() {

        doNothing().when(mInitializedLatch).countDown();

        CustomClass.methodB(customObject);
        try {
            CustomClass.methodA(context, "");
        } catch (Exception e) {
            e.printStackTrace();
        }
        verify(mInitializedLatch).countDown();

        try {
            doNothing().when(mInitializedLatch).await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Class.getCustomObject();
    }

Указанное c сообщение, которое я получаю при запуске customClassTest:

Wanted but not invoked:
mInitializedLatch.countDown();
-> at CustomClassTest.methodA(CustomClassTest.java:79)
Actually, there were zero interactions with this mock.

Wanted but not invoked:
mInitializedLatch.countDown();
-> at CustomClassTest.methodA(CustomClassTest.java:79)
Actually, there were zero interactions with this mock.

Запуск отладчика с точками останова на каждом из кажется, что соответствующие строки говорят о том, что тест выполняется нормально (все переменные назначаются правильно в нужных точках) до проверки (mInitializedLatch) .countDown () ;, когда появляется сообщение (и код прекращает работу).

Любая помощь приветствуется, спасибо.

ОБНОВЛЕНИЕ # 1:

Изменен код для удаления ключевого слова stati c:

import android.content.Context;
import android.util.Log;

import **.CustomObject;
import java.util.concurrent.CountDownLatch;
import androidx.annotation.NonNull;

public class CustomClass {
  private final String string = "a";
  private CustomObject customObject = null;
  private CountDownLatch initializedLatch = new CountDownLatch(1);

  @NonNull
  public CustomObject1 getCustomObject1() {
      try {
          initializedLatch.await();
          assert customObject != null;
          return customObject;

      } catch (InterruptedException e) {
        throw new RuntimeException(".");
      }
  }

  public void methodA(final Context context,
                                         final String string1,
                                         ) throws exception {
      initializedLatch.countDown();
  }


  public void methodB(@NonNull final CustomObject customObjectInput) {
      customObject = customObjectInput;
  }
}
import android.content.Context;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.util.concurrent.CountDownLatch;

import **.CustomObject;

import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;

import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;

@RunWith(MockitoJUnitRunner.class)
public class CustomClassTest{

    @Mock
    CustomObject customObject;

    @Mock
    Context context;

    @Mock
    CountDownLatch mCountDownLatch;

    @Mock
    CountDownLatch mInitializedLatch;

    @InjectMocks
    CustomClass customClass;

    @Before
    public void setUp() {
        customObject = Mockito.spy(CustomObject.class);
        context = Mockito.spy(Context.class);
    }

    @Test
    public void customClassTest() {

        doNothing().when(mInitializedLatch).countDown();

        customClass.methodB(customObject);
        try {
            customClass.methodA(context, "");
        } catch (Exception e) {
            e.printStackTrace();
        }
        verify(mInitializedLatch).countDown();

        try {
            doNothing().when(mInitializedLatch).await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        customClass.getCustomObject();
    }

Сообщения об ошибках Теперь читайте:

error: non-static method methodA(Context,String) cannot be referenced from a static context
error: non-static method getCustomObject1() cannot be referenced from a static context

Второе сообщение об ошибке отображается шесть раз. Кажется, код не компилируется.

Ответы [ 2 ]

0 голосов
/ 14 апреля 2020

Вы не получаете никаких вызовов, потому что фактический вызов не сделан с вашим смоделированным mInitializedLatch объектом.

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

Этого можно добиться, сделав объект, который вы хотите проверить, в качестве переменной экземпляра и передав объект-объект в конструктор.
Тогда вызовы будут сделанный из вашего смоделированного объекта, и mockito сможет их отследить.

Пример:

// Source Code
public class CustomerClass {
    private final CountDownLatch initializedLatch

    public CustomerClass(CountDownLatch initializedLatch) {
        this.initializedLatch = initializedLatch;
    }
}

Теперь используйте эту переменную экземпляра в своем коде вместо определенной вами переменной stati c .

В тестовом коде создайте конструктор CustomerClass, передав имитированный объект initializedLatch, и тогда он будет работать как шарм.

Если вы хотите инициализировать значение initializedLatch только там , Вы можете сделать то же самое, сохранив конструктор по умолчанию вместе с конструктором, который я определил выше.

Этот конструктор по умолчанию может вызывать параметризованный конструктор.

public CustomerClass() {
    this(new CountDownLatch(1));
}

Редактировать:

Вам также необходимо изменить исходную реализацию.

import android.content.Context;
import android.util.Log;

import **.CustomObject;
import java.util.concurrent.CountDownLatch;
import androidx.annotation.NonNull;

public class CustomClass {
  private static final String string = "a";
  private CustomObject customObject;
  private CountDownLatch initializedLatch;

  public CustomClass() {
    this(new CountDownLatch(1), null);
  }

  public CustomClass(CountDownLatch initializedLatch, CustomObject customObject) {
    this.initializedLatch = initializedLatch;
    this.customObject = customObject;
  }

  @NonNull
  public CustomObject1 getCustomObject1() {
      try {
          initializedLatch.await();
          assert customObject != null;
          return customObject;

      } catch (InterruptedException e) {
        throw new RuntimeException(".");
      }
  }

  public void methodA(final Context context final String string1) throws Exception {
      initializedLatch.countDown();
  }


  public void methodB(@NonNull final CustomObject customObjectInput) {
      customObject = customObjectInput;
  }
}

Теперь вышеупомянутая реализация источника будет использовать initializedLatch и customObject , предоставленные в конструкторе. .

Тестовый код

import android.content.Context;

import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.util.concurrent.CountDownLatch;

import **.CustomObject;

import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;

import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;

@RunWith(MockitoJUnitRunner.class)
public class CustomClassTest{

    @Mock
    CustomObject customObject;

    @Mock
    Context context;

    @Mock
    CountDownLatch mInitializedLatch;

    @InjectMocks
    CustomClass customClass;

    @Before
    public void setUp() {
        customClass = new CustomClass(mInitializedLatch, customObject);
    }

    @Test
    public void customClassTest() {

        doNothing().when(mInitializedLatch).countDown();

        customClass.methodB(customObject);
        try {
            customClass.methodA(context, "");
        } catch (Exception e) {
            e.printStackTrace();
        }
        verify(mInitializedLatch).countDown();

        try {
            doNothing().when(mInitializedLatch).await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        customClass.getCustomObject();
    }

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

0 голосов
/ 14 апреля 2020

В CustomClass CountDownLatch объявляется как поле c stati и инициализируется. Если вы отладите свой класс, вы увидите, что Mockito не насмехается над этим полем. Все взаимодействие кода с объектом initializedLatch не перехватывается прокси-сервером Mockito, поэтому при настройке теста с помощью doNothing (). When (mInitializedLatch) .countDown () фактически вы не устанавливаете поле в customClass.So, когда вы используйте verify (mInitializedLatch) .countDown (), вы фактически говорите Mockito, что ожидаете одного взаимодействия с этим макетом, но никаких взаимодействий не происходит по вышеуказанной причине.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...