当前位置: 首页 > 知识库问答 >
问题:

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

金宣
2023-03-14

我在这里面临一个非常奇怪的问题。

以下是我的测试课程:

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));
    }

}

这里的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()中是测试用例它自己,我做了弄清楚为什么数据库管理器类的构造函数没有得到嘲弄(Observable.fromIterable(新的数据库管理器(). getGuide elinesListByPositionOnHome()))当代码在SearchViewModel类中时。

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

我得到的例外是:

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

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

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

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


共有1个答案

伏默
2023-03-14

我做得很好,但没有添加在PrepareForTest注释中调用构造函数的类。

因此,在我的情况下,这必须是:

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

这个stackoverflow的答案帮了我一把。

 类似资料:
  • 问题内容: 我正在尝试第一次使用PowerMockito模拟类构造函数,但是它不起作用。我当前的代码是: 测试失败,因为返回的值为“ Fail”。我的问题在哪里? 问题答案: Okey,找到答案了,您需要致电 代替

  • 考虑下面给出的代码: 我正在尝试编写一个单元测试用例: < li >调用< code >对象b。B()必须被嘲笑 < li >必须模拟对构造函数的调用 这就是我使用Mockito和Powermockito所做的: 第一个模拟成功工作,但第二个模拟使用 失败,并出现以下错误: org.powermock.reflect.exceptions.ConstructorNotFoundException:

  • 为了测试一些遗留代码,我必须使用powermockito。原因是遗留代码没有使用依赖项注入,并且由于某些原因,我们现在无法重构代码。我们正在系统中使用ANT运行testng。我已经配置了构建。xml使用power mock和power mock testng库。我想用powermockito模拟一个构造函数,下面是示例代码。 这次测试失败了,我不知道这里出了什么问题。我还看到下面的链接配置测试与电

  • 我正在为我的java类编写测试类。我将Junit5与Mockito一起使用。 我使用的Junit5与Power Mockito不兼容,所以我只使用Mockito。 我有,它具有下面这样的函数,并且在构造函数中初始化了。 当我编写测试用例时,我模拟了,但是由于我们在一个方法中创建,我如何模拟,这样我就可以编写期望值,根据我在测试类中设置的选择获得值?

  • 我是莫基托的新手。假设我有一节这样的课 我正在使用Mockito编写一个JUnit测试,我正在使用构造函数创建类的对象。当我安装类时,是否可以模拟Drew()方法?

  • 有了Deck对象之后,我们有必要初始化其中的Card对象。上一章的buildDeck函数稍作修改就可使用,但是更自然的方法是为Deck类再添加一个构造函数,代码如下: Deck::Deck () { apvector<Card> temp (52); cards = temp; int i = 0; for (Suit suit = CLUBS; suit <= SPADES; s