Mockito 4.8.0无法Mock构造方法:测试断言失败返回null
问题原因分析
你遇到的测试失败,核心是测试代码中手动创建的Author Mock实例,和控制器方法内部new Author()生成的实例是两个完全不同的对象。你给前者设置的方法返回值,无法作用到后者身上,所以控制器调用方法后返回默认的null。
解决方案
方案一:通过mockConstruction回调统一设置所有实例行为
利用mockConstruction的回调参数,在每个Author实例被创建时,直接定义其方法的返回逻辑,这样控制器内部创建的实例也会遵循这个行为:
@Test public void testGetStringBuiltByComplexProcess01() { final String firstName = "firstName"; final String lastName = "lastName"; final String expectedResult = "when worked"; try (MockedConstruction<Author> ignored = mockConstruction(Author.class, (mock, context) -> { // 对所有通过new创建的Author实例,统一设置方法返回值 when(mock.methodWhichMakesNetworkAndDatabaseCalls(eq(firstName), eq(lastName))) .thenReturn(expectedResult); })) { // 调用控制器方法 String actualResult = ut.getStringBuiltByComplexProcess(firstName, lastName); // 断言结果 assertEquals(expectedResult, actualResult, "Strings should match"); // 获取控制器内部创建的实例,验证方法调用 Author createdAuthor = ignored.constructed().get(0); verify(createdAuthor).methodWhichMakesNetworkAndDatabaseCalls(eq(firstName), eq(lastName)); } }
方案二:获取控制器内部创建的实例再配置行为
先触发控制器创建Author实例,再通过mockConstruction.constructed()拿到该实例,配置其方法行为后重新调用验证:
@Test public void testGetStringBuiltByComplexProcess01() { final String firstName = "firstName"; final String lastName = "lastName"; final String expectedResult = "when worked"; try (MockedConstruction<Author> mockConstruction = mockConstruction(Author.class)) { // 第一次调用,触发控制器内部创建Author实例 ut.getStringBuiltByComplexProcess(firstName, lastName); // 获取控制器创建的那个Mock实例 Author createdAuthor = mockConstruction.constructed().get(0); // 给该实例设置方法返回值 when(createdAuthor.methodWhichMakesNetworkAndDatabaseCalls(eq(firstName), eq(lastName))) .thenReturn(expectedResult); // 第二次调用,验证返回值 String actualResult = ut.getStringBuiltByComplexProcess(firstName, lastName); assertEquals(expectedResult, actualResult, "Strings should match"); // 验证方法调用 verify(createdAuthor).methodWhichMakesNetworkAndDatabaseCalls(eq(firstName), eq(lastName)); } }
关键注意点
mockConstruction的作用是拦截try代码块内所有new Author()的创建动作,返回Mock实例,但每次new都会生成一个独立的Mock对象。- 不要将测试代码中手动创建的Mock实例,和控制器内部生成的实例混淆,二者是不同的对象,配置不会互通。
内容的提问来源于stack exchange,提问作者Oxnard
相关产品推荐
相关产品推荐

