Swapnil Kadam
Swapnil Kadam

Reputation: 4293

How to provide object inside public method to access another method within it using PowerMock?

I am writing unit test case for a Class

public class CurrentMoreInfoDataProvider implements CurrentMoreInfoInterface.presenterToModel{

private CurrentMoreInfoInterface.modelToPresenter modelToPresenter;

public CurrentMoreInfoDataProvider(CurrentMoreInfoInterface.modelToPresenter modelToPresenter) {
    this.modelToPresenter = modelToPresenter;
}

@Override
public void provideData() {
    WeatherApiResponsePojo apiWeatherData = WeatherDataSingleton.getInstance().getApiWeatherData();
    if(null != apiWeatherData.getCurrently()){
        CurrentlyPojo currently = apiWeatherData.getCurrently();
        if(null != currently){
            populateWeatherData(currently);
        }
    }
}

public void populateWeatherData(CurrentlyPojo currently) {....}

I want to just use verify method of power mock to test whether populateWeatherData get executed or not. Below is my test case so far.

@RunWith(PowerMockRunner.class)
@PrepareForTest(CurrentMoreInfoDataProvider.class)
public class TestCurrentMoreInfoDataProvider {

    private CurrentMoreInfoDataProvider dataProvider;
    @Mock
    CurrentMoreInfoInterface.modelToPresenter modelToPresenter;

    private CurrentlyPojo currentlyPojo = new CurrentlyPojo();
    @Test
    public void testPopulateWeatherData(){

        dataProvider = PowerMockito.spy(new CurrentMoreInfoDataProvider(modelToPresenter));
        dataProvider.provideData();
        Mockito.verify(dataProvider).populateWeatherData(currentlyPojo);
    }
}

If I run this I get null pointer exception in provideData method at

if(null != apiWeatherData.getCurrently()){

How should I provide apiWeatherData to provideData method in that class?

Upvotes: 0

Views: 125

Answers (2)

Timothy Truckle
Timothy Truckle

Reputation: 15622

You have to mock WeatherDataSingleton.getInstance().getApiWeatherData() too.

This would be much easier if you would not use static access in general and the Singelton pattern in particular.


I tried mocking it, but how should i provide that mock object to provideData() ?

  1. create a mock of WeatherDataSingleton.
  2. Configure your Test so that this mock is used (by properly using dependency injection or by surrendering to your bad design using Powermock).
  3. configure the mock to return the data:

    doReturn(currentlyPojo).when(weatherDataSingletonMock).getApiWeatherData();
    

This resolves the NPE.

Upvotes: 1

Maciej Kowalski
Maciej Kowalski

Reputation: 26522

I dont think you need to go for PowerMockito if you apply a simple refactor to your production code:

public class CurrentMoreInfoDataProvider{

@Override
public void provideData() {
    WeatherApiResponsePojo apiWeatherData = getApiWeatherData();
    if(null != apiWeatherData.getCurrently()){
        CurrentlyPojo currently = apiWeatherData.getCurrently();
        if(null != currently){
            populateWeatherData(currently);
        }
    }
}

WeatherApiResponsePojo getApiWeatherData(){
   return WeatherDataSingleton.getInstance().getApiWeatherData();
}

then in your test expect that new method to return certain object:

@RunWith(MockitoJUnitRunner.class)
public class TestCurrentMoreInfoDataProvider {


    private CurrentMoreInfoDataProvider dataProvider;
    @Mock
    CurrentMoreInfoInterface.modelToPresenter modelToPresenter;
    @Mock
    WeatherApiResponsePojo apiWeatherDataMock;

    private CurrentlyPojo currentlyPojo = new CurrentlyPojo();
    @Test
    public void testPopulateWeatherData(){

        dataProvider = PowerMockito.spy(new CurrentMoreInfoDataProvider(modelToPresenter));

        doReturn(apiWeatherDataMock).when(dataProvider).getApiWeatherData();

        dataProvider.provideData();
        Mockito.verify(dataProvider).populateWeatherData(currentlyPojo);
    }
}

Upvotes: 1

Related Questions