Mocking Network response for unit test case

DeltaCap019 :

I am trying to create a test case for AlbumsController which fetches data from the network and parses it.

AlbumService: Responsible for network call and getting data. ( Assume it can be anything that performs some async task and gives callback accordingly so as to avoid "Server" specific mocking solutions )

public class AlbumsController {

    public void getAlbums(final ServiceCallback<AlbumsWrapper> albumsServiceCallback) {

        new AlbumsService().fetchAlbums(new ServiceCallback<NetworkResponse>() {
            @Override
            public void onSuccess(NetworkResponse response) {
                // parse response
            }

            @Override
            public void onFailure(NetworkResponse error) {
                // do something for Failure
            }
        });
    }



public class AlbumControllerTest {

    @Mock
    private ServiceCallback<NetworkResponse> serviceCallback;

    @Captor
    private ArgumentCaptor<ServiceCallback<AlbumsWrapper>> albumsWrapper;

    @Captor
    private  ArgumentCaptor<ServiceCallback<NetworkResponse>> networkResponseArgumentCaptor;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void parseAlbums_EmptyList_ReturnsTrue() {

// below are different ways I am trying with no success so far.
        AlbumsController albumsController = new AlbumsController();
        albumsController.getAlbums(albumsWrapper.capture());


        NetworkResponse response = new NetworkResponse();
        networkResponseArgumentCaptor.capture();
        networkResponseArgumentCaptor.getValue().onSuccess(response);
    }
}

Aim:

  • To mock AlbumService inside getAlbums method so that instead of getting data from the server I should be able to call onSuccess() with my test data as an argument. And is it possible to get the list after parsing so as that I can assert base on the data in the list?
  • I don't want to move code responsible for parsing to some method and make that public. My intention here is to understand how to handle such a case.
  • Open for refactoring of code if that's what is required to be taken care of in TDD.
  • Full solution or pointers to look for both are appreciated.

Libraries

  • mockito-core:2.2.9
  • junit:4.12
Maciej Kowalski :

If small refactoring is the option then:

1) Move the new AlbumsService() to a package level method:

AlbumService createAlbumService(){
    return new AlbumService();
}

...

public void getAlbums(final ServiceCallback<AlbumsWrapper> albumsServiceCallback) {

    createAlbumService().fetchAlbums(new ServiceCallback<NetworkResponse>()

package visibility is enough as the test class will be in the same package as the AlbumController.

2) Spy the AlbumController:

@Spy
private AlbumsController albumsControllerSpy = new AlbumController();

@Mock 
private AlbumService albumServiceMock;

3) Make the createAlbumService() method return your mock:

@Test
public void parseAlbums_EmptyList_ReturnsTrue() {

    doReturn(albumServiceMock).when(albumControllerSpy).createAlbumService();
    ...

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=159902&siteId=1
Recommended