'How to mock a void method with PowerMockito?
This is a duplicate of this question. There are bunch of similar questions/answers as well but none helped me. As there are hundreds of developers accepted some answers I am probably wrong somewhere and have no idea where is my problem!
This is my sample class and I want to test its method.
final class NavigationBuilder {
@VisibleForTesting List<Intent> mIntentList = new ArrayList<>(5);
@VisibleForTesting
void addNextScreenBasedOnBookingStatus(final Booking booking) {
final ChatMsgDbAsyncHelper helper = new ChatMsgDbAsyncHelper();
if (booking == null) {
helper.cleanAllMessages(mContext); // <= Crash here
}
}
}
This is my test class:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ChatMsgDbAsyncHelper.class, SplashActivity.class})
public class NavigationBuilderTest {
private SplashActivity mActivity;
private NavigationBuilder mNavBuilder;
@Before
public void setUp() throws Exception {
mActivity = new SplashActivity();
ISplashView view = mock(ISplashView.class);
PassengerStorage passengerStorage = mock(PassengerStorage.class);
mNavBuilder = new NavigationBuilder(mActivity, view, passengerStorage);
}
@Test
public void addNextScreenBasedOnBookingStatus_whenBookingIsNull() throws Exception {
ChatMsgDbAsyncHelper spy = PowerMockito.spy(new ChatMsgDbAsyncHelper());
PowerMockito.doNothing().when(spy).cleanAllMessages(mActivity);
mNavBuilder.addNextScreenBasedOnBookingStatus(null);
assertTrue(mNavBuilder.mIntentList.isEmpty());
}
}
Test fails and the reason is NullPointerException because test is running logic inside of helper.cleanAllMessages(mContext);. My expectation from above mock is those logic should not be performed.
Caused by: java.lang.NullPointerException at com.xxx.xxx.db.entities.ChatMessageTable.(ChatMessageTable.java:23)
Solution 1:[1]
Your logic in the given code is to do nothing when you're passing mActivity object: PowerMockito.doNothing().when(spy).cleanAllMessages(mActivity);
But what you're actually passing is null:
mNavBuilder.addNextScreenBasedOnBookingStatus(null);
Also, you have to pass this "spy" object in the test class to make your mock logic work. May be you can try something like this -
PowerMockito.whenNew(ChatMsgDbAsyncHelper.class).withNoArguments().thenReturn(spy);
PowerMockito.doNothing().when(spy).cleanAllMessages(mActivity); // or null, as per your requirement
and then pass your mActivity object to the method:
mNavBuilder.addNextScreenBasedOnBookingStatus(mActivity); // or pass null, as per your requirement
Solution 2:[2]
The problem was my understanding :)
I changed signature of the method under test with following and could test it. So in this case I am passing instance of ChatMsgDbAsyncHelper to the method rather than create it within method.
@VisibleForTesting
void addNextScreenBasedOnBookingStatus(final Booking booking, final ChatMsgDbAsyncHelper chatMsgHelper) {
...
}
and test works fine now:
@Test
public void addNextScreenBasedOnBookingStatus_whenBookingIsNull() throws Exception {
ChatMsgDbAsyncHelper mChatMsgHelper = PowerMockito.spy(new ChatMsgDbAsyncHelper());
doNothing().when(mChatMsgHelper).cleanAllMessages(any(Context.class));
mNavBuilder.addNextScreenBasedOnBookingStatus(null, mChatMsgHelper);
assertTrue(mNavBuilder.mIntentList.isEmpty());
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | blu3 |
| Solution 2 | Hesam |
