无法使用Mockito模拟构造函数

rqdpfwrv  于 2022-11-08  发布在  其他
关注(0)|答案(2)|浏览(267)

使用Mockito 4.8.0版
我需要测试的控制器方法

@GetMapping(value = "getStringBuiltByComplexProcess")
 public String getStringBuiltByComplexProcess(@RequestParam String firstName, @RequestParam String lastName ) {
  Author a = new Author();
  return a.methodWhichMakesNetworkAndDatabaseCalls(firstName, lastName);
 }

以下是测试方法

@Test
 public void testGetStringBuiltByComplexProcess01() {
  final String firstName = "firstName";
  final String lastName = "lastName";
  try (MockedConstruction<Author> mock = mockConstruction(Author.class)) {
   Author authorMock = new Author();
   when(authorMock.methodWhichMakesNetworkAndDatabaseCalls(eq(firstName), eq(lastName))).thenReturn("when worked");
   assertEquals("when worked", ut.getStringBuiltByComplexProcess(firstName, lastName),  "Strings should match");
   verify(authorMock).methodWhichMakesNetworkAndDatabaseCalls(eq(firstName), eq(lastName));
  }
 }

失败,并显示以下消息

org.opentest4j.AssertionFailedError: strings should match ==> expected: <when worked> but was: <null>

在这个简化的例子中,控制器方法有更多的代码,但是不起作用的核心是模拟控制器方法构造的对象。

ncgqoxb0

ncgqoxb01#

您在线上创建的对象

Author authorMock = new Author();

与在getBooksByAuthor()函数中创建的不同。调试器应该会向您显示这一点。
您可以使用mock.constructed().get(0)来获取在getBooksByAuthor()中创建的对象,但是当您可以这样做时,getBooksByAuthor()已经完成了,您不能用该mock做太多事情。
我不清楚你的目标是什么,我猜你想检查Author对象是以某种方式创建的,而涉及getFullName()的行不是实际代码的一部分,只是你为了实验而添加的东西,因为它们什么也不做。
如果你想验证传递给dataAccessService的对象是否满足某些条件,你需要的是一个ArgumentCaptor

ArgumentCaptor<Author> authorCaptor = ArgumentCaptor.forClass(Author.class);
when(dataAccessServiceMock.getBooks(authorCaptor.capture())).thenReturn(books);

List<Book> result = ut.getBooksByAuthor(firstName, lastName);

Author author = authorCaptor.value();
assertEquals(firstName, author.getFirstName());
m4pnthwp

m4pnthwp2#

如果您使用MockInitializer进行存根,它应该可以解决您的问题:

try (MockedConstruction<Author> mocked = mockConstruction(Author.class, (mock, context) -> {
        when(authorMock.methodWhichMakesNetworkAndDatabaseCalls(eq(firstName), eq(lastName))).thenReturn("when worked");
        })) {

        assertEquals("when worked", ut.getStringBuiltByComplexProcess(firstName, lastName),  "Strings should match");
        verify(authorMock).methodWhichMakesNetworkAndDatabaseCalls(eq(firstName), eq(lastName));

        }
}

但是一个更好的测试控制器的方法是使用MockMvc。它允许你测试一个给定的HTTP请求,你是否正确地配置了spring-mvc,使它可以正确地做以下事情:

  • 如果可以正确解析HTTP请求以使用预期的参数执行预期的控制器方法
  • 如果它可以将从控制器方法返回的对象反序列化为预期的JSON结构,则可以使用该方法。
  • 它允许配置进行HTTP调用的当前用户,并验证该用户是否有足够的权限调用此API,如果没有,它是否会返回预期的错误响应
  • 等等。

所有这些东西都不能用你的脆弱的模拟构造函数方法来测试。
有关MockMvc的详细信息,请参阅this guide

相关问题