Java中如何mock通过new关键字创建的对象?结合示例代码说明
针对Java中new关键字创建对象的Mock方案
以下是基于你提供的代码场景可使用的三种实现方案:
方案1:代码重构(最推荐)
硬编码new对象会导致强耦合,优先推荐通过依赖注入或者工厂模式剥离对象创建逻辑,修改后的业务代码示例:
public class TestClass { private final MyObject myobject; private SecondObject secondObject; // 注入SecondObject工厂 private final SecondObjectFactory secondObjectFactory; // 构造方法注入工厂 public TestClass(MyObject myObject, SecondObjectFactory secondObjectFactory) { this.myObject = myObject; this.secondObjectFactory = secondObjectFactory; } public void init() { secondObject = secondObjectFactory.create(myobject,100,100); } // 工厂接口定义,也可以用Supplier等函数式接口简化 public interface SecondObjectFactory { SecondObject create(MyObject obj, int arg1, int arg2); } }
测试时直接mock工厂的create方法返回mock的SecondObject即可,测试代码示例:
// 测试代码示例 MyObject mockMyObject = mock(MyObject.class); SecondObject mockSecondObject = mock(SecondObject.class); SecondObjectFactory mockFactory = mock(SecondObjectFactory.class); when(mockFactory.create(mockMyObject, 100, 100)).thenReturn(mockSecondObject); TestClass testClass = new TestClass(mockMyObject, mockFactory); testClass.init(); // 后续即可对mockSecondObject进行行为验证
方案2:使用Mockito原生构造Mock(Mockito 3.5.0+版本支持)
如果无法修改原有代码,可以用Mockito提供的mockConstruction方法拦截指定类的构造调用,直接返回mock对象,测试代码示例:
@Test void testInit() { MyObject mockMyObject = mock(MyObject.class); TestClass testClass = new TestClass(mockMyObject); SecondObject mockSecondObject = mock(SecondObject.class); // 拦截SecondObject的所有构造调用,返回mock对象 try (MockedConstruction<SecondObject> mocked = mockConstruction(SecondObject.class, (mock, context) -> { // 可以校验构造参数是否符合预期 assertEquals(mockMyObject, context.arguments().get(0)); assertEquals(100, context.arguments().get(1)); assertEquals(100, context.arguments().get(2)); })) { testClass.init(); // 拿到构造出来的mock对象做验证 SecondObject constructed = mocked.constructed().get(0); // 后续验证逻辑 } }
注意:mockConstruction作用域只在try-with-resources代码块内,超出范围就会失效
方案3:使用PowerMock框架(适合低版本Mockito场景)
如果使用的Mockito版本低于3.5.0,可以用PowerMock的whenNew能力拦截构造调用:
- 首先引入PowerMock相关依赖
- 测试类加上
@RunWith(PowerMockRunner.class)和@PrepareForTest(TestClass.class)注解(注意准备的是创建new对象的类,也就是TestClass,不是SecondObject)
测试代码示例:
@RunWith(PowerMockRunner.class) @PrepareForTest(TestClass.class) public class TestClassTest { @Test public void testInit() throws Exception { MyObject mockMyObject = mock(MyObject.class); SecondObject mockSecondObject = mock(SecondObject.class); // 拦截SecondObject的构造调用,参数匹配的话返回mock对象 PowerMockito.whenNew(SecondObject.class) .withArguments(mockMyObject, 100, 100) .thenReturn(mockSecondObject); TestClass testClass = new TestClass(mockMyObject); testClass.init(); // 后续验证逻辑 } }
内容的提问来源于stack exchange,提问作者FranzWagner
相关产品推荐
相关产品推荐

