【问题标题】:Spock Testing Framework with Spring Boot to test REST Controller使用 Spring Boot 测试 REST 控制器的 Spock 测试框架
【发布时间】:2021-06-30 13:25:03
【问题描述】:

我已经使用 spring boot 编写了 rest api 这是控制器代码

    @RestController
    public class ApiController {
    
        @Autowired
        private ApiService apiService;
        
            @PostMapping(path = "/user", consumes = {MediaType.APPLICATION_JSON_VALUE}, 
produces = {MediaType.APPLICATION_JSON_VALUE})
        @LogTransaction
        public ResponseEntity<String> user(HttpServletRequest request) {
               //apiService.getUser() method call database so i need to mock  it 
               USer user = apiService.getUser(request);
              return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(user);
        }
    }
    

这个 api 工作正常,我已经在 groovy 中使用 spock 框架编写了测试

    @SpringBootTest
    class ApiControllerTest extends Specification {
    
    @Autowired
    private ApiController apiController;
    
    @Autowired
    private ApiService apiService;
    
    
    @Autowired
    MockMvc mockMvc
        
    def "User api"() {
            given:
            def User user = new User()      
            apiService.getUser(_) >> user
    
            when:
            def result = mockMvc.perform(MockMvcRequestBuilders
                    .post("/user")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content("""
    {
     "username":"demo",
     "password":"demo"
    }
    """))
                    .andReturn()
    
            then:
            assert result.response.status == HttpStatus.OK.value()
    
    }

这也很好用。方法 apiService.getUser(request) 调用数据库。我想嘲笑它。但它每次都调用数据库。所以我试图在这里使用@Autowired 模拟 apiService.getUser(request) 但它对我不起作用,并且这个方法每次都执行并调用数据库。任何人都可以分享模拟控制器的 apiService.getUser(request) 方法的方法。

【问题讨论】:

    标签: spring-boot groovy spock


    【解决方案1】:

    您可以通过使用 @SpringSpy 注释 Spring bean 来部分模拟 Spring bean。

    因此,在您的情况下,您只需将 @Autowired 替换为 @SpringSpy:

      @SpringSpy
      private ApiService apiService;
    

    它应该可以工作。

    【讨论】:

      【解决方案2】:

      您可以对诸如

      之类的数据源使用排除项
      @SpringBootTest
      @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
      @AutoConfigureMockMvc
      public class Class1Test{
          @Autowired
          private MockMvc mockMvc;
      
          @MockBean
          private RestTemplate restTemplate;
      
          @MockBean
          private IYourRepository repository;
      
          @Autowired
          private SecurityJwtSettings securityJwtSettings;
      
      
      

      使用 mockito,您可以模拟对数据库的请求:

      Mockito.doAnswer(x->{
                  YourEntity entityToSave = x.getArgument(0);
                  entityToSave.setCreatedAt(LocalDateTime.now());
                  Assert.assertEquals("tester.admin.01",entityToSave.getAuthorizedBy());
                  Assert.assertEquals("tester.01", entityToSave.getRequestedBy());
                  return entityToSave;
              }).when(repository).save(Mockito.any(YourEntity.class));
      

      【讨论】:

      • 问题是关于 Spock,而不是 Mockito。
      • @LucasCosta 这个问题是关于 Spock 的。将 Mockito 与 Spock 一起使用会被认为是一种非常糟糕的代码味道,因为 Spock 已经内置了模拟机制。
      猜你喜欢
      • 2017-06-28
      • 2022-01-19
      • 2018-06-23
      • 1970-01-01
      • 2019-03-07
      • 2018-01-02
      • 2021-02-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多