繁体   English   中英

Mockito:无法模拟在 object 上调用的方法

[英]Mockito: Can't mock method called on object

我不允许发布真实代码,但这基本上是正在发生的事情:

  • 我们有一个实现接口InterfaceOne的 class InterfaceOneImpl和一个实现InterfaceTwoImplInterfaceTwo

  • InterfaceTwoImplInterfaceOneImpl中被实例化,并且InterfaceTwoImpl.makeHttpRequest()被调用,但我需要在我的单元测试中模拟这个 function 因为我显然不想在其中发出 http 请求。 makeHttpRequest是一个公共的、非静态的 function,它返回一个字符串

我的代码做这样的事情:

public class InterfaceOneImpl implements InterfaceOne{
    public String processRequest(...){
        ...
        InterfaceTwo obj = new InterfaceTwoImpl();
        obj.makeHttpRequest();
        ...
    }
}

我的测试 class 看起来像这样:

public TestInterfaceOneImpl {
    ....
    @Test
    public void testProcessRequest(){
        InterfaceOne interfaceOneImpl = new InterfaceOneImpl();
        InterfaceTwo mock = PowerMockito.mock(InterfaceTwoImpl.class);
        InterfaceTwo.when(mock.processRequest()).thenReturn("zzzz");
PowerMockito.whenNew(RiskValidationRestClientImpl.class).withNoArguments().thenReturn((RiskValidationRestClientImpl) mock);
        String reqStr = interfaceOneImpl.processRequest();
        
        //a bunch of failed assertions
    }
}

我的问题是 processRequest() 没有被正确模拟,因为该方法的源代码版本实际上正在运行而不是模拟。 当我在调试模式下单步执行单元测试的每一行时,我总是在 makeHttpRequest() function 的主体中结束。我做错了什么?

我的问题是 processRequest() 没有被正确模拟,因为该方法的源代码版本实际上正在运行而不是模拟。 当我在调试模式下单步执行单元测试的每一行时,我总是在 makeHttpRequest() function 的主体中结束。

我认为您的问题是错误的-根据您的示例, processRequestInterfaceOne上的一种方法,而mockInterfaceTwo的一个实例。

我假设你的意思是:

InterfaceTwo.when(mock.makeHttpRequest()).thenReturn("zzzz");

任何状况之下...

What am I doing wrong?

你认为你是 mocking 什么东西,但你根本不是。 让我们分解你的例子:

// First you create an instance of InterfaceOneImpl - OK
InterfaceOne interfaceOneImpl = new InterfaceOneImpl();

// Next you create a mock of InterfaceTwo (I think? I don't use PowerMock) - OK
InterfaceTwo mock = PowerMockito.mock(InterfaceTwoImpl.class);

// Then you tell the mock you created that it should return "zzzz" - OK
InterfaceTwo.when(mock.processRequest()).thenReturn("zzzz");

// Finally you call a method on your instance. YOU DO NOT USE "mock" in
// any way shape or form. As it's defined, "processRequest" creates a NEW
// instance of InterfaceTwo: InterfaceTwo obj = new InterfaceTwoImpl();
// and uses THAT instance. So of course you will always end up with the
// real method being called. You're creating a mock and literally never
// using it.
String reqStr = interfaceOneImpl.processRequest();

修复:实际使用你的模拟。 通过在 function 中传递它:

// Pass the object to use as an argument
public String processRequest(InterfaceTwo obj){
    ...
    obj.makeHttpRequest();
    ...
}

// And then your test:
@Test
public void testProcessRequest() {
    InterfaceOne interfaceOneImpl = new InterfaceOneImpl();
    InterfaceTwo mock = PowerMockito.mock(InterfaceTwoImpl.class);
    InterfaceTwo.when(mock.processRequest()).thenReturn("zzzz");

    // NOW you can use the mock
    String reqStr = interfaceOneImpl.processRequest(mock);
}

或者将其传递给 class:

public class InterfaceOneImpl implements InterfaceOne {

public InterfaceOneImpl(InterfaceTwo obj) {
    this.obj = obj;
}

public String processRequest(...){
        ...
        obj.makeHttpRequest();
        ...
    }
}

// And then your test
@Test
public void testProcessRequest(){
    InterfaceTwo mock = PowerMockito.mock(InterfaceTwoImpl.class);
    InterfaceTwo.when(mock.processRequest()).thenReturn("zzzz");

    // Now interface one will use the mock to do the request
    InterfaceOne interfaceOneImpl = new InterfaceOneImpl(mock);
    String reqStr = interfaceOneImpl.processRequest();
    
    //a bunch of failed assertions
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM