我正在尝试在集成测试中测试 Controller 的操作。这是一个简单的场景,我要测试的操作是调用服务的方法。我正在尝试使用元类覆盖该方法,但它看起来不起作用,即服务的实际方法总是被调用,而不是我使用元类覆盖的方法。我在这里做错了什么?
这是 Controller 的方法:
class MyController {
MyService myService
def methodA() {
def u = myService.find(params.paramA)
render view: "profile", model: [viewed: u]
}
这是我实现集成测试的方式:
class MyControllerTests extends GroovyTestCase {
MyController controller
void testMethodA() {
controller = new MyController()
// Mock the service
MyService mockService = new MyService()
mockService.getMetaClass().find = { String s ->
[]
}
controller = new MyController()
controller.myService = myService
controller.methodA()
}
附言我在 STS 2.9.2 中使用 grails 2.0.0
最佳答案
首先我推荐使用 Spock Framework这是一个非常好的测试库,除了integrates with Grails pretty well . 您的测试将如下所示:
@TestFor(MyController) // TestFor is builtin Grails annotation
class MyControllerSpec extends Specification {
// thanks to TestFor annotation you already have 'controller' variable in scope
MyService mockService = Mock(MyService)
// setup method is executed before each test method (known as feature method)
def setup() {
controller.myService = mockService
}
def 'short description of feature being tested'() {
given:
mockService.find(_) >> [] // this tells mock to return empty list for any parameter passed
when:
controller.methodA()
then:
// here goes boolean statements (asserts), example:
controller.response.text.contains 'Found no results'
}
}
如果您不想使用 Spock,对于 mock,您需要最简单的方法是使用 Groovy 强制转换。检查一下:
MyService mockService = [find: { String s -> [] }] as MyService
这是 map 强制。在您模拟单个方法的情况下,甚至不需要 Map,因此您可以将其编写得更简单。
MyService mockService = { String s -> [] } as MyService
这是闭包强制。好吧,也没有必要指定参数,因为您没有处理它。
MyService mockService = { [] } as MyService
最后一条语句基本上意味着 mockService 上调用的任何方法都将执行指定的闭包,因此结果将返回空列表。
越简单越好,干杯!
顺便说一句,在使用 Spock 时,您仍然可以使用强制模拟。 Spock 模拟(使用 Mock() 方法创建)可用于测试更高级的案例,例如交互。
更新:对于集成测试,您将扩展 IntegrationSpec 并且不需要使用 @TestFor。
关于testing - 在grails集成测试中重写服务方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13965363/