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

Android Unit Test с дооснащением и Mockito

Я выделил методы api для переопределения api из кода активности, и я хочу сделать unit test для этих методов, например: Интерфейс:

public interface LoginService {
    @GET("/auth")
    public void basicLogin(Callback<AuthObject> response);
}

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

public class AuthAPI {
    private Bus bus;
    LoginService loginService;

    public AuthAPI(String username, String password) {
        this.bus = BusProvider.getInstance().getBus();
        loginService = ServiceGenerator.createService(LoginService.class,
                CommonUtils.BASE_URL,
                username,
                password);
    }

    public void Login() {

        loginService.basicLogin(new Callback<AuthObject>() {
            @Override
            public void success(AuthObject authObject, Response response) {
                bus.post(authObject);
            }

            @Override
            public void failure(RetrofitError error) {
                AuthObject authObject = new AuthObject();
                authObject.setError(true);
                bus.post(authObject);
            }
        });
    }

}

И вот тест

@RunWith(MockitoJUnitRunner.class)
public class AuthCallTest extends TestCase {

    AuthAPI authAPI;

    @Mock
    private LoginService mockApi;

    @Captor
    private ArgumentCaptor<Callback<AuthObject>> cb;

    @Before
    public void setUp() throws Exception {
        authAPI = new AuthAPI("username", "password");
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testLogin() throws Exception {

        Mockito.verify(mockApi).basicLogin((cb.capture()));

        AuthObject authObject = new AuthObject();
        cb.getValue().success(authObject, null);

        assertEquals(authObject.isError(), false);
    }
}

когда я запускаю тест, у меня есть эта ошибка

Wanted but not invoked:
mockApi.basicLogin(<Capturing argument>);
-> at AuthCallTest.testLogin(AuthCallTest.java:42)
Actually, there were zero interactions with this mock.

Что я сделал не так, это сводит меня с ума Я старался следовать этому руководству без успеха: http://www.mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and-mockito.html

кто-то мне помогает: (

4b9b3361

Ответ 1

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

1) Образцы кода извлекаются из тестового класса, проверяющего конкретную активность. Как часть настройки (т.е. В @Before), она заменяет ссылку Activity на реализацию API GitHub макетной. Затем он вызывает Activity onCreate().

2) Во время onCreate(), активность вызывает вызов заменяемого теперь GitHub API, передавая его Callback объект.

Эти первые два шага объясняют, почему работает шаг Mockito.verify(mockApi).repositories(Mockito.anyString(), cb.capture()); в начале каждого теста. Когда тест выполняется после @Before, mockApi действительно вызвал свой метод repositories().

Остальная часть кода легче понять после этого. Поскольку он создал только mockApi, но не изменил фактический Callback, содержимое активности изменилось. Остальная часть кода затем проверяет, что эти изменения произошли, либо путем проверки ListView или Toasts.


Чтобы ответить на ваш вопрос, вам необходимо:

1) В начале вашего тестового метода замените объект AuthAPI loginService объектом mockApi, затем вызовите AuthAPI.Login().

2) Используйте verify(), поскольку вы уже должны проверить, что функция была вызвана.

3) Создайте образец AuthObject и передайте его функции cb.getValue().success().

4) Получите AuthObject из своего Bus и убедитесь, что он тот же, который вы отправили в функцию callback.success().

Это проверит, что ваш AuthAPI.Login() правильно отправит ваш Bus AuthObject, который он будет извлекать из "Дооснащения".


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

Ответ 2

Проблема заключается в том, что вы вызываете verify в неподходящий момент: целью verify является проверка того, что взаимодействия с mockApi были такими, какие вы ожидали. Поэтому обычно вы увидите что-то вроде:

authApi.login();
Mockito.verify(mockApi).basicLogin((cb.capture()));

Это также сообщение об ошибке: verify ожидается basicLogin, но это не так.

Я тоже прочитал эту статью и почувствовал, что чего-то не хватает. На самом деле я пока еще не обнаружил аргумент. Так что вы не можете с этим справиться:)