在另一种方法内部调用的模拟方法

时间:2018-09-25 16:23:32

标签: java unit-testing mockito powermockito

我正在尝试使用Powermock模拟对数据库的调用。这是我们的代码的示例:

public class WrapperClass {
    public static SearchUtil searchUtil = new SearchUtil();
}

public class SearchUtil {
    public Record searchForThing(String thing) {
        // Makes a call to a database and returns a record
    }
}

public class TestableClass {
    public void runMethod() {
        // When this is called, it returns null, however based on the debugger, WrapperClass.searchUtil is a mocked object
        WrapperClass.searchUtil.searchForThing("thing");
    }
}

@PrepareForTest(WrapperClass.class)
@PowerMockIgnore({"javax.management.*", "javax.xml.parsers.*", "com.sun.org.apache.xerces.internal.jaxp.*", "ch.qos.logback.*", "org.slf4j.*", "org.apache.xerces.*", "javax.xml.*", "org.xml.sax.*", "org.w3c.dom.*"})
@RunWith(PowerMockRunner.class)
public class MyTest {
    @Test
    public void runMyTest() {
        SearchUtil searchUtil = PowerMockito.mock(SearchUtil.class);
        PowerMockito.mockStatic(WrapperClass.class);
        Whitebox.setInternalState(WrapperClass.class, "searchUtil", searchUtil);
        PowerMockito.doReturn(new SearchRecord()).when(WrapperClass.searchUtil).searchForThing("thing");

        // When the below call is made, a new SearchRecord is returned and is not null
        WrapperClass.searchUtil.searchForThing("thing");

        // Calling the method that calls the searchForThing method, when searchForThing is called inside runMethod, it returns null
        new TestableClass().runMethod();
    }
 }

我知道静态变量等绝对不是最佳实践,但是现在让我们假装无法更改它。在测试中调用被模拟的调用时,它将按预期返回新的SearchRecord。在runMethod中调用该函数时,它返回null,但是searchUtil对象根据我的调试器的模拟对象。当调用存根方法的嵌套嵌套时,为什么会发生这种情况?

1 个答案:

答案 0 :(得分:0)

查看以下内容,其行为应与预期一样。

@PowerMockIgnore({"javax.management.*", "javax.xml.parsers.*", "com.sun.org.apache.xerces.internal.jaxp.*", "ch.qos.logback.*", "org.slf4j.*", "org.apache.xerces.*", "javax.xml.*", "org.xml.sax.*", "org.w3c.dom.*"})
@RunWith(PowerMockRunner.class)
@PrepareForTest(WrapperClass.class, TestableClass.class)
public class MyTest {
    @Test
    public void runMyTest() {
        //Arrange 
        Record expected = new SearchRecord();
        String arg = "thing";
        SearchUtil searchUtil = PowerMockito.mock(SearchUtil.class);
        when(searchUtil.searchForThing(arg)).thenReturn(expected);

        // mock all the static members in WrapperClass class
        PowerMockito.mockStatic(WrapperClass.class);
        // use Mockito to set up your expectation
        when(WrapperClass.searchUtil).thenReturn(searchUtil);

        TestableClass subject = new TestableClass();

        //Act
        subject.runMethod();

        //Assert
        //...
    }
 }

请注意测试流程。

我还建议确保测试中使用的参数与执行的方法传递的参数匹配,因为如果不匹配,则由于参数/参数不匹配,它也会返回 null

否则,您将需要松开参数匹配器

//...

when(searchUtil.searchForThing(any(String.class))).thenReturn(expected);

//...

您也可以查看the powermock-mockito docs here,以更好地了解如何使用该框架。

相关问题