Issue
I am facing a very weird issue here.
Following is my Test class:
SearchViewModel.java
@RunWith(PowerMockRunner.class)
@PrepareForTest({JSONReader.class, ConstantsPath.class, DatabaseManager.class})
public class SearchViewModelTest {
@Rule
public TestRule rule = new InstantTaskExecutorRule();
private String indexSearchContent;
private String fullTextSearchContentGL1, fullTextSearchContentGL2, fullTextSearchContentGL3, fullTextSearchContentGL4;
private String searchQuery = "a";
private List<FullTextSearchItem> fullTextSearchResult;
private String behaviorString;
private SearchViewModel searchViewModel;
private DatabaseManager databaseManager;
private void initInputs() throws IOException {
indexSearchContent = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getIndexSearchFilePath()));
behaviorString = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getBehavioralFilePath()));
fullTextSearchContentGL1 = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getFullTextSearchFilePath("1")));
fullTextSearchContentGL2 = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getFullTextSearchFilePath("2")));
fullTextSearchContentGL3 = JSONReader.convertStreamToString(getClass().getClassLoader().getResourceAsStream(ConstantsPath.getInstance().getFullTextSearchFilePath("3")));
}
private void mockDaggerDependency() {
AppInfo appInfo = Mockito.mock(AppInfo.class);
Mockito.when(appInfo.getAppName()).thenReturn("testApp");
Mockito.when(appInfo.getAppLanguage()).thenReturn("EN");
TestApplicationModule module = new TestApplicationModule(appInfo);
DatabaseModule databaseModule = Mockito.mock(DatabaseModule.class);
Component component = DaggerComponent.builder().applicationModule(module).databaseModule(databaseModule).build();
MyApplication.setComponent(component);
}
private void mockGuidelineList() throws Exception {
databaseManager = PowerMockito.mock(DatabaseManager.class);
List<Guideline> mockedGls = new ArrayList<>();
Guideline gl = new Guideline();
gl.setGuidelineId("1");
mockedGls.add(gl);
gl = new Guideline();
gl.setGuidelineId("2");
mockedGls.add(gl);
gl = new Guideline();
gl.setGuidelineId("3");
mockedGls.add(gl);
Mockito.when(databaseManager.getGuidelinesListByPositionOnHome()).thenReturn(mockedGls);
PowerMockito.whenNew(DatabaseManager.class).withNoArguments().thenReturn(databaseManager);
// prepare expected output for fulltext search
Observable.fromIterable(new DatabaseManager().getGuidelinesListByPositionOnHome())
.map(Guideline::getGuidelineId)
.flatMap(glId -> BehavioralFile.<List<FullTextSearchItem>>loadJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath(glId),
new TypeToken<List<FullTextSearchItem>>() {
}.getType()).toObservable()
.flatMapIterable(fullTextSearchitems -> fullTextSearchitems)
.filter(item -> item.getText().toLowerCase().contains(searchQuery.toLowerCase()))).<List<FullTextSearchItem>>toList()
.subscribe(list -> {
fullTextSearchResult = list;
});
}
@Before
public void setUp() throws Exception {
MainActivityTest.overrideRxJavaPlugins();
mockDaggerDependency();
initInputs();
PowerMockito.mockStatic(JSONReader.class);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getIndexSearchFilePath())).willReturn(indexSearchContent);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath("1"))).willReturn(fullTextSearchContentGL1);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath("2"))).willReturn(fullTextSearchContentGL2);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath("3"))).willReturn(fullTextSearchContentGL3);
BDDMockito.given(JSONReader.readJsonFile(ConstantsPath.getInstance().getBehavioralFilePath())).willReturn(behaviorString);
mockGuidelineList();
searchViewModel = new SearchViewModel();
}
@After
public void tearDown() throws Exception {
}
@Test
public void loadFullTextSearch() throws Exception {
//searchViewModel.loadFullTextSearch_(searchQuery);
loadFullTextSearch(searchQuery);
assertEquals(searchViewModel.fullTextSearchListLiveData.getValue().size(), fullTextSearchResult.size());
}
private void loadFullTextSearch(String query) {
// following line is throwing exception if put in another class.
Observable.fromIterable(new DatabaseManager().getGuidelinesListByPositionOnHome())
.map(Guideline::getGuidelineId)
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(Schedulers.io())
.flatMap(glId -> BehavioralFile.<List<FullTextSearchItem>>loadJsonFile(ConstantsPath.getInstance().getFullTextSearchFilePath(glId),
new TypeToken<List<FullTextSearchItem>>() {
}.getType()).toObservable()
.flatMapIterable(fullTextSearchitems -> fullTextSearchitems)
.filter(item -> item.getText().toLowerCase().contains(query.toLowerCase()))).<List<FullTextSearchItem>>toList().toObservable()
.subscribe(list -> searchViewModel.fullTextSearchListLiveData.setValue(list));
}
}
here loadFullTextSearch()
test cases works perfectly fine until i remove comment of line searchViewModel.loadFullTextSearch_(searchQuery);
,
check modified test case:
@Test
public void loadFullTextSearch() throws Exception {
searchViewModel.loadFullTextSearch_(searchQuery);
//loadFullTextSearch(searchQuery);
assertEquals(searchViewModel.fullTextSearchListLiveData.getValue().size(), fullTextSearchResult.size());
}
Here comes the weird part: both the functions(earchViewModel.loadFullTextSearch_()
, loadFullTextSearch()
) has same code but loadFullTestSearch_()
is in SearchViewModel class and loadFullTextSearch()
in is test cases it self, that i did to figure out why constructor of DatabaseManager class is not getting mocked(Observable.fromIterable(new DatabaseManager().getGuidelinesListByPositionOnHome())
) when code is in SearchViewModel
class.
Note: I am mocking constructor of DatabaseManager class. check mockGuidelineList()
method. Mocked method is working if constructor is getting invoked in same test class.
Exception i get is :
java.lang.NullPointerException: Cannot return null from a non-@Nullable @Provides method
Because i am using dagger and the constructor i am mocking initialises database object dependency.
public DatabaseManager() {
MyApplication.getComponent().inject(this);
}
Any help would be appreciated, Thanks.
Solution
I was doing everything fine but missed to add class where constructor is being invoked in @PrepareForTest
annotation.
So in my case this has to be:
@PrepareForTest({JSONReader.class, ConstantsPath.class, DatabaseManager.class, SearchViewModel.class})
this stackoverflow answer helped me out.
Answered By - chandil03
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.