Search code examples
robolectricpowermockandroid-annotations

Fail to run test with AndroidAnnotation, Robolectric and PowerMock


I am new to unit test and I am trying to use robolectric to do the test for my android app, but I encountered some problems

DemoPresenterTest

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 23)
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
@PrepareForTest(DemoPresenterImpl_.class)
public class DemoPresenterTest {

    @Rule
    public MockitoRule rule = MockitoJUnit.rule();

    private MockDemoNetworkService mMockDemoNetworkService;
    private MockLceView mLceView;

    private DemoPresenterImpl_ mPresenter;

    @Before
    public void setup() {

        mMockDemoNetworkService = Mockito.mock(MockDemoNetworkService.class);
        mLceView = Mockito.mock(MockLceView.class);
        PowerMockito.mockStatic(DemoPresenterImpl_.class);

        mPresenter = DemoPresenterImpl_.getInstance_(RuntimeEnvironment.application);

        mPresenter.service = mMockDemoNetworkService;
        mPresenter.view = mLceView;
    }

    @Test
    public void testDownloadData() {

        mPresenter.downloadData();
        Mockito.verify(mLceView).onError(Mockito.anyInt());
    }
}

DemoPresenterImpl

@EBean
public class DemoPresenterImpl implements DemoPresenter {

    @Bean(DemoNetworkService.class)
    DemoService service;

    protected LceView<Demo> view;

    /**
     * download the data from server for the first time, data will be saved into the database
     * and for the next time it will query the database instead
     */
    @Override
    @Background(delay = 1000)
    public void downloadData() {

        try {

            List<Demo> result = service.getDemoList();

            if (result != null) {
                view.setData(result);
            } // add else if the result is not return empty list but null

        } catch (NetworkFailException e) {
            view.onError(e.getResponse().getCode());
        }
    }

    @Override
    public void attach(LceView<Demo> view) {
        this.view = view;
    }
}

MockDemoNetworkService

public class MockDemoNetworkService implements DemoService {

    @Override
    public List<Demo> getDemoList() throws NetworkFailException {

        NetworkFailResponse response = new NetworkFailResponse();
        response.setCode(500);

        throw new NetworkFailException(response);
    }

    @Override
    public boolean setDemoList(List<Demo> demoList) {
        return false;
    }
}

When I run the test it returns "Cannot subclass final class class com.*.DemoPresenterImpl_", if I change to DemoPresenterImpl, the test can run but the mLceView never get called

Wanted but not invoked: mockLceView.onError(); -> at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:245) Actually, there were zero interactions with this mock.

am I doing something wrong?


Solution

  • I think you can remove @PrepareForTest, because you are not mocking the presenter, you are actually testing it. Then you should use DemoPresenterImpl_, because it is containing the needed generated code.