繁体   English   中英

如何在 Spock 中创建通用 CRUD controller 测试

[英]How to create a generic CRUD controller test in Spock

甚至可以在 Spock 中为 Spring controller 创建通用单元测试吗? 我在 Spring Boot 中有一个抽象的 controller,它由一些特定的控制器扩展。 结果是每个 controller 都有相同的 CRUD 实现。 所以,现在我想为这些控制器创建类似的单元测试,但我不能在 Spock 测试中使用构造函数。 我收到错误

CrudControllerTest.groovy
Error:(16, 5) Groovyc: Constructors are not allowed; instead, define a 'setup()' or 'setupSpec()' method
IngredientControllerTest.groovy
Error:(7, 5) Groovyc: Constructors are not allowed; instead, define a 'setup()' or 'setupSpec()' method

对于以下代码

abstract class CrudControllerTest<T, R extends JpaRepository<T, Long>, C extends CrudController<T,R>> extends Specification {
    private String endpoint
    private def repository
    private def controller
    private MockMvc mockMvc
 
    CrudControllerTest(def endpoint, R repository, C controller) {
        this.endpoint = endpoint
        this.repository = repository
        this.controller = controller
        this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build()
    }
 
    def "Should get 404 when product does not exists"() {
        given:
        repository.findById(1) >> Optional.empty()
        when:
        def response = mockMvc.perform(MockMvcRequestBuilders.get(endpoint + '/1')).andReturn().response
        then:
        response.status == HttpStatus.NOT_FOUND.value()
    }
}
 
class IngredientControllerTest extends CrudControllerTest<Ingredient, IngredientRepository, IngredientController> {
    
    IngredientControllerTest() {
        def repository = Mock(IngredientRepository)
        super("/ingredients", repository, new IngredientController(Mock(repository)))
    }
}

这里还有其他方法可以在 Spock 中实现通用单元测试吗?

您不能将构造函数用于Specifications ,而是可以使用模板方法模式。 要么使用单独的方法:

abstract class CrudControllerTest extends Specification {
    private String endpoint
    private def repository
    private def controller
    private MockMvc mockMvc
 
    def setup() {
        endpoint = createEndpoint()
        repository = createRepository()
        controller = createController()
        mockMvc = MockMvcBuilders.standaloneSetup(controller).build()
    }
    
    abstract createEndpoint()
    abstract createRepository()
    abstract createController()
 
    def "Should get 404 when product does not exists"() {
        given:
        repository.findById(1) >> Optional.empty()
        when:
        def response = mockMvc.perform(MockMvcRequestBuilders.get(endpoint + '/1')).andReturn().response
        then:
        response.status == HttpStatus.NOT_FOUND.value()
    }
}
 
class IngredientControllerTest extends CrudControllerTest<Ingredient, IngredientRepository, IngredientController> {
    
    def createEndpoint() {
        "/ingredients"
    }
    def createRepository {
        Mock(IngredientRepository)
    }
    def createController() {
        new IngredientController(repository)
    }
}

或者使用返回所有内容的方法,这会更好一些,因为您的某些值需要引用另一个值:

abstract class CrudControllerTest extends Specification {
    private String endpoint
    private def repository
    private def controller
    private MockMvc mockMvc
 
    def setup() {
        (endpoint, repository, controller) = createSut()
        mockMvc = MockMvcBuilders.standaloneSetup(controller).build()
    }
    
    abstract createSut()
 
    def "Should get 404 when product does not exists"() {
        given:
        repository.findById(1) >> Optional.empty()
        when:
        def response = mockMvc.perform(MockMvcRequestBuilders.get(endpoint + '/1')).andReturn().response
        then:
        response.status == HttpStatus.NOT_FOUND.value()
    }
}
 
class IngredientControllerTest extends CrudControllerTest<Ingredient, IngredientRepository, IngredientController> {
    
    def createSut() {
        def repo = Mock(IngredientRepository)
        ["/ingredients", repo, new IngredientController(repository)]
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM