我正在尝试在集成测试中测试控制器的操作。这是一个简单的场景,我正在尝试测试的操作是调用服务的方法。我试图使用元类覆盖该方法,但看起来它不起作用,即服务的实际方法总是被调用而不是我使用元类覆盖的方法。我在这里做错了什么?
这是控制器的方法:
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()
}
P.S。我在STS 2.9.2中使用grails 2.0.0
答案 0 :(得分:8)
首先,除了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,那么对于模拟,您需要最简单的方法是使用 Groovy强制。看看这个:
MyService mockService = [find: { String s -> [] }] as MyService
这是地图强制。在你的情况下,当模拟单个方法时,甚至不需要Map,所以你可以更简单地编写它。
MyService mockService = { String s -> [] } as MyService
这是关闭强制。好吧,由于你没有处理它,所以不需要指定参数。
MyService mockService = { [] } as MyService
最后一个语句基本上意味着在 mockService 上调用的任何方法都将执行指定的闭包,因此将在结果中返回空列表。
更简单更好,干杯!
顺便说一下,当使用Spock时,你仍然可以使用强制模拟。 Spock模拟(使用Mock()方法创建)对于测试更高级的案例非常有用,例如交互。
更新:对于集成测试,您将扩展IntegrationSpec,并且不需要使用@TestFor。
答案 1 :(得分:1)
我建议您使用Grails注释来模拟您的服务,如以下示例摘自文档10.1 Unit Testing:
@Mock([Book, Author, BookService])
然后测试控制器如下:
void testSearch() {
def control = mockFor(SearchService)
control.demand.searchWeb { String q -> ['mock results'] }
control.demand.static.logResults { List results -> }
controller.searchService = control.createMock()
controller.search() assert controller.response.text.contains "Found 1 results"
}