【问题标题】:Java Mockito Can't mock the result of methodJava Mockito无法模拟方法的结果
【发布时间】:2021-03-13 11:02:51
【问题描述】:

我在从控制器中测试(模拟方法的值)我的删除方法时遇到问题。在普通模式下它可以正常工作,但在我测试时却不行。

这是我的代码。

我的控制器

@RestController
@RequestMapping("/")
public class MainController {

    @DeleteMapping(value = "/deletePost/{id}")
public ResponseEntity<String> deletePost(@PathVariable int id) throws SQLException {
    boolean isRemoved = postsService.deletePost(connection, id);

    if (!isRemoved)
        return new ResponseEntity<>("Post with given id was not found", HttpStatus.NOT_FOUND);
    else {
        modifiedPostsService.insertModificationData(connection, new ModificationData(id, "deletion"));
        return new ResponseEntity<>("Post with given id has been deleted.", HttpStatus.OK);
    }
}
}

我的帖子服务

    public boolean deletePost(Connection connection, int id) throws SQLException {
    return postsDao.deletePost(connection, id);
}

我的帖子道

    @Override
public boolean deletePost(Connection connection, int id) throws SQLException {
    boolean isPostExists = isPostExist(connection, id);
    PreparedStatement ps;
    ps = connection.prepareStatement("delete from POSTS where ID = " + id);
    ps.executeUpdate();
    return isPostExists;
}

最后是我的测试

@WebMvcTest(MainController.class)
class MainControllerTests {

@Autowired
private MockMvc mockMvc;

@MockBean
private Connection connection;

@MockBean
private PostsService mockPostsService;

@Test
void testIfDeletePostUrlIsOk() throws Exception {
    Mockito.when(mockPostsService.deletePost(connection, 1)).thenReturn(true);
    mockMvc.perform(MockMvcRequestBuilders
            .delete("/deletePost/1")
            .accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk());
}

}

testIfDeletePostUrlIsOk() 返回 404 而不是 200(我猜模拟值 - true 不起作用,而是 false)。为什么以及如何解决这个问题?

【问题讨论】:

  • 您刚刚创建了服务的本地模拟,但您的控制器不会自动使用它。您需要以某种方式注入模拟。
  • 但是我不知道怎么做;(

标签: java spring spring-boot testing mocking


【解决方案1】:

当你使用时:

Mockito.mock(...)

您正在本地范围内创建一个模拟对象,您必须将其注入您的 SUT 或使用:

@MockBean

MockBean 将使您的对象可以通过 spring 的 ApplicationContext 访问,因此 spring 可以选择您的模拟。

【讨论】:

  • 感谢您的帮助,但幸运的是它仍然无法正常工作,同样的错误,404 而不是 200。
  • 使用 mockPostsService.deletePost(org.mockito.ArgumentMatchers.any(Connection.class), 1) 匹配任何类型连接的输入,mockito 使用对象引用来匹配你的方法调用和你的模拟。
  • 你的意思是:Mockito.when(mockPostsService.deletePost(org.mockito.ArgumentMatchers.any(Connection.class), 1)).thenReturn(true); ?
  • 没错,你也可以导入静态的 org.mockito.ArgumentMatchers。
  • org.mockito.ArgumentMatchers.anyInt()
【解决方案2】:
@SpringBootTest
@AutoConfigureMockMvc
public class TestingWebApplicationTest {

 @Autowired
 private MockMvc mockMvc;

 @MockBean     
 Connection mockConnection;

 @MockBean
 PostsService mockPostsService;

 @Test
 void testIfDeletePostUrlIsOk() throws Exception {
 Mockito.when(mockPostsService.deletePost(any(), anyInt())).thenReturn(true);
 mockMvc.perform(MockMvcRequestBuilders
        .delete("/deletePost/1")
        .accept(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk());
 }
}

你需要将你的模拟注入控制器,注解@SpringBootTest 和@MockBean 将完成这项工作

【讨论】:

  • 感谢您的帮助,但不幸的是它仍然无法正常工作,同样的错误,404 而不是 200。
  • 你能在控制器中调试并检查你的代码是否返回 404 吗?你在用junit5吗?请在此处复制您从测试类中导入的内容
  • 在控制器中,当数据库中没有具有给定 ID 的帖子(这是我的模型)时,也可能有 404 代码状态,否则有 200。我使用的是 JUNIT 5.7.0。这是我的一些导入(空间不足): import org.junit.jupiter.api.Test;导入 org.mockito.Mockito;导入 org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;导入 org.springframework.boot.test.mock.mockito.MockBean;导入 org.springframework.http.MediaType;导入 org.springframework.test.web.servlet.MockMvc;导入静态 org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  • 是的,我知道,这就是为什么我要求您放置调试断点并检查是否从您的控制器方法或服务器应用程序返回 404
  • Mockito.when(mockPostsService.deletePost(any(), anyInt())).thenReturn(true)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多