Тестирование модуля. Повторная установка вызова api с помощью Mockito – ArgumentCaptor

Простите меня, если мой вопрос выглядит дублированным, но я не понимаю, как тестировать API-интерфейс для переоснащения. Build.gradle на уровне приложения

dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile("com.android.support.test.espresso:espresso-core:$rootProject.ext.expressoVersion", { exclude group: 'com.android.support', module: 'support-annotations' }) compile "com.android.support:appcompat-v7:$rootProject.ext.supportLibraryVersion" compile "com.jakewharton:butterknife:$rootProject.ext.butterKnifeVersion" annotationProcessor "com.jakewharton:butterknife-compiler:$rootProject.ext.butterKnifeVersion" // Dependencies for local unit tests testCompile "junit:junit:$rootProject.ext.junitVersion" testCompile "org.mockito:mockito-all:$rootProject.ext.mockitoVersion" testCompile "org.hamcrest:hamcrest-all:$rootProject.ext.hamcrestVersion" testCompile "org.powermock:powermock-module-junit4:$rootProject.ext.powerMockito" testCompile "org.powermock:powermock-api-mockito:$rootProject.ext.powerMockito" compile "com.android.support.test.espresso:espresso-idling-resource:$rootProject.ext.espressoVersion" // retrofit, gson compile "com.google.code.gson:gson:$rootProject.ext.gsonVersion" compile "com.squareup.retrofit2:retrofit:$rootProject.ext.retrofitVersion" compile "com.squareup.retrofit2:converter-gson:$rootProject.ext.retrofitVersion" } 

Build.gradle на уровне проекта имеет этот дополнительный контент

// Определение версий в одном месте

 ext { // Sdk and tools minSdkVersion = 15 targetSdkVersion = 25 compileSdkVersion = 25 buildToolsVersion = '25.0.2' supportLibraryVersion = '23.4.0' junitVersion = '4.12' mockitoVersion = '1.10.19' powerMockito = '1.6.2' hamcrestVersion = '1.3' runnerVersion = '0.5' rulesVersion = '0.5' espressoVersion = '2.2.2' gsonVersion = '2.6.2' retrofitVersion = '2.0.2' butterKnifeVersion = '8.5.1' expressoVersion = '2.2.2' } 

Основная деятельность

 public class MainActivity extends AppCompatActivity implements MainView { @BindView(R.id.textViewApiData) TextView mTextViewApiData; @BindView(R.id.progressBarLoading) ProgressBar mProgressBarLoading; private MainPresenter mMainPresenter; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); initializeComponents(); } private void initializeComponents() { mMainPresenter = new MainPresenter(this); mMainPresenter.presentDataFromApi(); } @Override public void onResponseReceived(final String response) { mTextViewApiData.setText(response); } @Override public void onErrorReceived(final String message) { mTextViewApiData.setText(message); } @Override public void showProgressDialog(final boolean enableProgressDialog) { mProgressBarLoading.setVisibility(enableProgressDialog ? View.VISIBLE : View.GONE); } } 

MainView

 public interface MainView { void onResponseReceived(String response); void onErrorReceived(String message); void showProgressDialog(boolean enableProgressDialog); } 

ApiClient

 public class ApiClient { private static Retrofit sRetrofit; public static Retrofit getInstance() { if (sRetrofit == null) { sRetrofit = new Retrofit.Builder() .baseUrl(Constants.Urls.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } return sRetrofit; } } 

Ведущий

 public class MainPresenter { private final MainView mMainView; private final Call<List<UserResponse>> mCallListUserResponse; public MainPresenter(final MainView mainView) { this.mMainView = mainView; final ApiInterface apiInterface = ApiClient.getInstance().create(ApiInterface.class); mCallListUserResponse = apiInterface.getUsers(); } public void presentDataFromApi() { mMainView.showProgressDialog(true); mCallListUserResponse.enqueue(new Callback<List<UserResponse>>() { @Override public void onResponse(final Call<List<UserResponse>> call, final Response<List<UserResponse>> response) { mMainView.onResponseReceived(Constants.DummyData.SUCCESS); mMainView.showProgressDialog(false); } @Override public void onFailure(final Call<List<UserResponse>> call, final Throwable t) { mMainView.onErrorReceived(Constants.DummyData.ERROR); mMainView.showProgressDialog(false); } }); } } 

ApiInterface

 public interface ApiInterface { @GET(Constants.Urls.USERS) Call<List<UserResponse>> getUsers(); } 

Константы

 public class Constants { public class Urls { public static final String BASE_URL = "https://jsonplaceholder.typicode.com"; public static final String USERS = "/users"; } } 

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

 public class MainPresenterTest { @InjectMocks private MainPresenter mMainPresenter; @Mock private MainView mMockMainView; @Mock private Call<List<UserResponse>> mUserResponseCall; @Captor private ArgumentCaptor<Callback<List<UserResponse>>> mArgumentCaptorUserResponse; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); } @Test public void presentDataFromApiTest() throws Exception { mMainPresenter.presentDataFromApi(); verify(mMockMainView).showProgressDialog(true); // verify(mUserResponseCall).enqueue(mArgumentCaptorUserResponse.capture()); // verify(mMockMainView).onResponseReceived(Constants.DummyData.SUCCESS); // verify(mMockMainView).showProgressDialog(false); } } 

Журнал

 Wanted but not invoked: mUserResponseCall.enqueue( <Capturing argument> ); -> at com.example.ranaranvijaysingh.testingdemo.presenters.MainPresenterTest.presentDataFromApiTest(MainPresenterTest.java:69) Actually, there were zero interactions with this mock. 

    Ваш код выглядит корректно синтаксически. Тем не менее, я подозреваю, что @InjectMock не может вводить макет-объект в конечные переменные экземпляра. Возможно, что при вызове mMainPresenter.presentDataFromApi () переменная ниже используется как реальный экземпляр:

     private final Call<List<UserResponse>> mCallListUserResponse; 

    Вам следует попробовать вручную вставить переменную mock в этот класс и назначить mCallListUserResponse, чтобы иметь возможность получить от экземпляра mockito.

    Возможно, стоит попробовать следующие шаги:

    1. Внесите переменную mCallListUserResponse в MainPresenter как неконфиденциальную.

    2. Добавьте метод в класс MainPresenter, как показано ниже:

      Void setUserResponseCall (Call> userResponse) {mCallListUserResponse = userResponse; }

    3. Теперь в классе Test выполните следующие действия:

    Измените свой тест ниже.

     @Test public void presentDataFromApiTest() throws Exception { //Set mock instance of the user response mMainPresenter.setUserResponseCall(mUserResponseCall); //real object call to presentDataFromApi(); mMainPresenter.presentDataFromApi(); verify(mMockMainView).showProgressDialog(true); verify(mUserResponseCall).enqueue(mArgumentCaptorUserResponse.capture()); } 

    Надеюсь, поможет.

    Вам нужно выполнить следующие шаги:

    1. Вводить свои макеты через бегун или через код:

       @RunWith(MockitoJUnitRunner.class) 

      или

       MockitoAnnotations.initMocks(this) 
    2. @Mock поля, которые вы хотите @Mock

    3. Аннотировать с @InjectMocks вы хотите проверить (в вашем случае ведущий)

    4. Убедитесь, что поля, которые вы хотите высмеять, – это поля в классе, который вы хотите протестировать (а не локальные переменные, такие как userResponseCall в вашем примере), иначе эти поля не будут введены.

    Проверьте это для аналогичного примера: https://github.com/matoelorriaga/pokemon/blob/master/app/src/test/java/com/melorriaga/pokemon/presenter/MainPresenterTest.java

    Intereting Posts
    Сделайте снимок экрана с помощью MediaProjection Требуется версия Gradle 2.2. Текущая версия 2.10 Строка заголовка продолжает отображаться, даже с помощью requestWindowFeature или андроида: тема Новый интерфейс Google Now и Google+ Автоматическое соединение Bluetooth с сопряженными устройствами Прозрачный AlertDialog имеет черный фон {"Error": {"message": "(# 324) Требуется загрузить файл", "type": "OAuthException", "code": 324}} Как правильно реализовать фид (аналогично Facebook / Instagram) в Android? Правильный способ обработки муравей для библиотеки Android. Строка исключает R.class из файла jar Мне нужно написать собственный код обработки прокси для OkHttp на Android? Как удалить выбранный элемент из списка с помощью CursorAdapter Layout_below элемент внутри включенного макета Установите ImageView (и его src) на ширину макета и сделайте его пропорциональную высоту OpenCV на Android с использованием Eclipse Libgdx и TWL: сила приложения Android закрывается в любом меню TWL, отлично работает на рабочем столе