使用 mockito-inline 库对本地创建的对象进行模拟方法调用

Mocking method call on object created locally using mockito-inline library

为了模拟本地 variable/method 调用在被测方法内部构造的本地对象,我们目前正在使用 PowerMockito 库。

我们正在尝试评估是否可以使用 mockito-inline(版本 3.7.7)来做同样的事情。 简而言之,我们正在尝试使用 Mockito.mockConstruction 拦截对象的构造,以便我们可以在本地创建的对象上指定模拟行为。

这里有一个场景描述了我们的用法。由于这是遗留代码,我们现在无法更改它。(例如,更改对实例变量的依赖或一些其他重构)

简而言之,classMyClass的execute()方法是在本地构造Utilclass的对象。由于我们想要对 execute() 的核心逻辑进行单元测试,因此需要模拟在 class MyClass.

的 execute() 方法中创建的本地 Util 对象上调用的 process() 方法
public class MyClass {

    public String execute(){

        Util localUtil = new Util();
        String data =  localUtil.process();

        //Core logic of the execute() method that needs to be unit tested...
        //Further update data based on logic define in process() method.
        data = data + " core logic";

        return data;
    }
}

public  class Util {
    public String process(){
        String result = "real";
        //Use various other objects to arrive at result
        return result;
    }
}

@Test
public void testLocalVar(){

        Util util = new Util();
        Assertions.assertEquals("real", util.process()); 

        try (MockedConstruction<Util> mockedConstruction = Mockito.mockConstruction(Util.class);) {

            util = new Util();
            when(util.process()).thenReturn("mocked method data");
            String actualData = util.process();
        
            //This works on local object created here.        
            Assertions.assertEquals("mocked method data",actualData);
            
            //Object,method under test
            MyClass myClass = new MyClass();
            actualData = myClass.execute();
            //This doesn't not works on local object created inside method under test 
            Assertions.assertEquals("mocked method data" + " core logic",actualData); //Fails

        }
    }

在这里,我们可以在测试方法内部本地创建的对象的方法上定义模拟行为。但是在被测实际方法中创建的本地对象不可能发生同样的事情。

我可以看到 mockedConstruction.constructed() 确实创建了 class 的每个对象 但无法在 execute() 方法中的 localUtil.process() 上指定模拟行为 ..

任何建议..

在您的情况下,您必须在指示 Mockito 模拟构造函数时对行为进行存根。 Mockito.mockConstruction() 已重载,不仅允许传递要模拟构造函数的 class:

@Test
void mockObjectConstruction() {
  try (MockedConstruction<Util> mocked = Mockito.mockConstruction(Util.class,
      (mock, context) -> {
        // further stubbings ...
        when(mock.process()).thenReturn("mocked method data");
   })) {
 
     MyClass myClass = new MyClass();
     actualData = myClass.execute();
  }
}

您可以在此 article 中找到更多可能的存根场景。