Android – unit testing using mockito for transformation API call – argumentcaptor

Please forgive me if my question looks repetitive, but I don't get how to test and transform API calls. Build.gradle at the application level

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"
}

The project level build. Gradle has this extra content

//Define versions in one place

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'
}

Main activities

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 one rrorReceived(final String message) {
        mTextViewApiData.setText(message);
    }

    @Override
    public void showProgressDialog(final boolean enableProgressDialog) {
        mProgressBarLoading.setVisibility(enableProgressDialog ? View.VISIBLE : View.GONE);
    }
}

Mainview for

public interface MainView {

    void onResponseReceived(String response);

    void one rrorReceived(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;
    }
}

host

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();
}

constant

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

This is what I want to do, but it doesn't work. The test case will now pass because I commented on 3 lines in the last line. After uncommenting these lines, you can see the errors. Test case

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);
    }
}

journal

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.

resolvent:

Your code looks syntactically correct. However, I suspect @ injectmock cannot inject mock objects into the final instance variables. When you call mmainpresenter. Presentdatafromapi(), the following variables may be used as instances:

private final Call<List<UserResponse>> mCallListUserResponse;

You should try to manually inject the mock variable into this class and assign it to the mcalllistuserresponse so that it can be obtained from the mockito instance

It may be worth trying the following steps:

>Set the variable mcalllistuserresponse in the mainpresenter to non final. > add a method in the mainpresenter class, as shown below:

Void setuserresponsecall (call > userresponse) {mcalllistuserresponse = userresponse;} > now do the following in the test class:

Modify your test as follows

@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());
    }

I hope I can help you

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>