java - 测试时模拟@Service 连接到数据库

标签 java spring unit-testing mockito spring-test

我正在尝试测试我的 Spring REST Controller ,但我的 @Service 始终尝试连接到数据库。

Controller :

@RestController
@RequestMapping(value = "/api/v1/users")
public class UserController {

private UserService userService;

@Autowired
public UserController(UserService userService) {
    this.userService = userService;
}

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<List<User>> getAllUsers() {
    List<User> users = userService.findAll();
    if (users.isEmpty()) {
        return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);
    }

    return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}

测试:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
public class UserControllerTest {

private MockMvc mockMvc;

@Autowired
private WebApplicationContext wac;

@Before
public void setup() {
    this.mockMvc = webAppContextSetup(wac).build();
}

@Test
public void getAll_IfFound_ShouldReturnFoundUsers() throws Exception {
    User first = new User();
    first.setUserId(1);
    first.setUsername("test");
    first.setPassword("test");
    first.setEmail("test@email.com");
    first.setBirthday(LocalDate.parse("1996-04-30"));

    User second = new User();
    second.setUserId(2);
    second.setUsername("test2");
    second.setPassword("test2");
    second.setEmail("test2@email.com");
    second.setBirthday(LocalDate.parse("1996-04-30"));

    UserService userServiceMock = Mockito.mock(UserService.class);  

    Mockito.when(userServiceMock.findAll()).thenReturn(Arrays.asList(first, second));

    mockMvc.perform(get("/api/v1/users")).
            andExpect(status().isOk()).
            andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)).
            andExpect(jsonPath("$", hasSize(2))).
            andExpect(jsonPath("$[0].userId", is(1))).
            andExpect(jsonPath("$[0].username", is("test"))).
            andExpect(jsonPath("$[0].password", is("test"))).
            andExpect(jsonPath("$[0].email", is("test@email.com"))).
            andExpect(jsonPath("$[0].email", is(LocalDate.parse("1996-04-30")))).
            andExpect(jsonPath("$[1].userId", is(2))).
            andExpect(jsonPath("$[1].username", is("test2"))).
            andExpect(jsonPath("$[1].password", is("test2"))).
            andExpect(jsonPath("$[1].email", is("test2@email.com"))).
            andExpect(jsonPath("$[1].email", is(LocalDate.parse("1996-04-30"))));

    verify(userServiceMock, times(1)).findAll();
    verifyNoMoreInteractions(userServiceMock);
}
}

我的测试总是失败,因为它从数据库读取数据,而不是获取第一个和第二个作为返回。如果我关闭数据库,它会抛出NestedServletException,嵌套:DataAccessResourceFailureException

如何正确测试它?我做错了什么?

最佳答案

以这种方式模拟 userService UserService userServiceMock = Mockito.mock(UserService.class); 不会将其注入(inject)到 Controller 中。删除此行并注入(inject) userService,如下所示

@MockBean UserService userServiceMock;

正如 @M.Deinum 建议的那样,您可以删除 MockMvc 的手动创建并 Autowiring 它

@Autowired
private MockMvc mockMvc;

最后你的代码应该看起来像

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
public class UserControllerTest {

    @MockBean 
    UserService userServiceMock;

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void getAll_IfFound_ShouldReturnFoundUsers() throws Exception {
       User first = new User();
       first.setUserId(1);
       first.setUsername("test");
       first.setPassword("test");
       first.setEmail("test@email.com");
       first.setBirthday(LocalDate.parse("1996-04-30"));

       User second = new User();
       second.setUserId(2);
       second.setUsername("test2");
       second.setPassword("test2");
       second.setEmail("test2@email.com");
       second.setBirthday(LocalDate.parse("1996-04-30"));

       Mockito.when(userServiceMock.findAll())
           .thenReturn(Arrays.asList(first, second));

       mockMvc.perform(get("/api/v1/users")).
        andExpect(status().isOk()).
        andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)).
        andExpect(jsonPath("$", hasSize(2))).
        andExpect(jsonPath("$[0].userId", is(1))).
        andExpect(jsonPath("$[0].username", is("test"))).
        andExpect(jsonPath("$[0].password", is("test"))).
        andExpect(jsonPath("$[0].email", is("test@email.com"))).
        andExpect(jsonPath("$[0].email", is(LocalDate.parse("1996-04-30")))).
        andExpect(jsonPath("$[1].userId", is(2))).
        andExpect(jsonPath("$[1].username", is("test2"))).
        andExpect(jsonPath("$[1].password", is("test2"))).
        andExpect(jsonPath("$[1].email", is("test2@email.com"))).
        andExpect(jsonPath("$[1].email", is(LocalDate.parse("1996-04-30"))));

        verify(userServiceMock, times(1)).findAll();
        verifyNoMoreInteractions(userServiceMock);
    }
}

关于java - 测试时模拟@Service 连接到数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44067910/

相关文章:

java - 在运行时根据输入从属性文件中获取值 - java Spring

Java Play POST [参数缺失]错误?

java - 在Spring上使用Jersey时从HK2收到“找不到合适的构造函数”

java - 你能从你的程序中检查你的操作系统和 java 运行时是 32 位还是 64 位吗?

java - Spring Boot 3 - 使用 RSA256 公钥验证 JWT token

c++ - Qt中的单元测试高度依赖(网络依赖)功能

unit-testing - 如何运行多个 Groovy 单元测试

java - 如何区分 "run all tests"和 "run just this test"?

java 命令不会执行我的 .class 文件

java - OpenGL:正方形不绘制到窗口(没有错误)