PowerMockito:如果代码位于另一个类中,则无法模拟构造函数



我在这里遇到了一个非常奇怪的问题。

以下是我的测试类:

搜索视图模型.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));
    }
}

在这里loadFullTextSearch()测试用例工作得很好,直到我删除第 searchViewModel.loadFullTextSearch_(searchQuery); 行的注释,

检查修改后的测试用例:

@Test
public void loadFullTextSearch() throws Exception {
        searchViewModel.loadFullTextSearch_(searchQuery);
        //loadFullTextSearch(searchQuery);
        assertEquals(searchViewModel.fullTextSearchListLiveData.getValue().size(), fullTextSearchResult.size());
    }

奇怪的部分来了:两个函数(earchViewModel.loadFullTextSearch_()loadFullTextSearch()(具有相同的代码,但loadFullTestSearch_()在SearchViewModel类中,loadFullTextSearch()是它自己的测试用例,我这样做是为了弄清楚为什么当代码在类中时,DatabaseManager类的构造函数不会被嘲笑(Observable.fromIterable(new DatabaseManager().getGuidelinesListByPositionOnHome()) SearchViewModel(。

注意:我正在模拟数据库管理器类的构造函数。 检查mockGuidelineList()方法。如果在同一测试类中调用构造函数,则模拟方法正在工作。

我得到的例外是:

java.lang.NullPointerException: Cannot return null from a non-@Nullable @Provides method

因为我正在使用dagger,而我正在模拟的构造函数初始化数据库对象依赖关系。

public DatabaseManager() {
    MyApplication.getComponent().inject(this);
}

任何帮助将不胜感激,谢谢。

我做得很好,但错过了添加在注释中调用构造函数@PrepareForTest类。

所以就我而言,这必须是:

@PrepareForTest({JSONReader.class, ConstantsPath.class, DatabaseManager.class, SearchViewModel.class})

这个堆栈溢出答案帮助了我。

相关内容

  • 没有找到相关文章

最新更新