使用 Spock 进行测试时,Grails 无法向域注入服务
Grails Can't inject service to domain when test with Spock
使用 Spock 进行 grails 单元测试时,无法自动将服务实例注入域。
下面是我的代码。
服务:
class HiService {
public HiService(){
println "Init HiService," + this.toString()
}
def sayHi(String name){
println "Hi, ${name}"
}
}
域:
class User {
public User(){
if (hiService == null){
println "hiService is null when new User(${name})"
}
}
String name
def hiService
def sayHi(){
println "Before use hiService " + hiService?.toString()
hiService.sayHi(name)
println "End use hiService" + hiService?.toString()
}
}
测试用例:
@TestFor(HiService)
@Mock([User])
class HiServiceTest extends Specification {
def "test sayHi"() {
given:
def item = new User( name: "kitty").save(validate: false)
when: "Use service method"
item.sayHi()
then : "expect something happen"
assertEquals(1, 1)
}
}
以下是控制台日志:
--Output from test sayHi--
Init HiService,test.HiService@530f5e8e
hiService is null when new User(null)
Before use hiService null
| Failure: test sayHi(test.HiServiceTest)
| java.lang.NullPointerException: Cannot invoke method sayHi() on null object
at test.User.sayHi(User.groovy:17)
at test.HiServiceTest.test sayHi(HiServiceTest.groovy:20)
服务已初始化,但无法注入域。但是当 运行 直接应用时,服务会自动注入域
如果您不想自动装配,则需要进行集成测试。如果使用 Grails 3 则使用 @Integration 注释,如果使用 grails 2 则扩展 IntegrationSpec。
参见:http://docs.grails.org/latest/guide/testing.html#integrationTesting
@Mock([User, HiService])
class HiServiceTest extends Specification {
def "test sayHi"() {
// ....
}
}
由于您正在编写单元测试,因此您的服务不会自动装配。此外,当您对 User class 对象进行单元测试时,您应该在 UserSpec 中编写测试(而不是 UserServceTest;Suffixing Spec 是 Spock 中的约定)。现在您可以像这样模拟 HiService:
class UserSpec 扩展规范 {
def "User is able to say hi"() {
given:
User user = new User(name: 'bla bla')
and: "Mock the user service"
def hiService = Mock(HiService)
user.hiService = hiService
when:
user.sayHi()
then:
1 * sayHiService.sayHi(user.name)
}
}
使用 Spock 进行 grails 单元测试时,无法自动将服务实例注入域。
下面是我的代码。
服务:
class HiService {
public HiService(){
println "Init HiService," + this.toString()
}
def sayHi(String name){
println "Hi, ${name}"
}
}
域:
class User {
public User(){
if (hiService == null){
println "hiService is null when new User(${name})"
}
}
String name
def hiService
def sayHi(){
println "Before use hiService " + hiService?.toString()
hiService.sayHi(name)
println "End use hiService" + hiService?.toString()
}
}
测试用例:
@TestFor(HiService)
@Mock([User])
class HiServiceTest extends Specification {
def "test sayHi"() {
given:
def item = new User( name: "kitty").save(validate: false)
when: "Use service method"
item.sayHi()
then : "expect something happen"
assertEquals(1, 1)
}
}
以下是控制台日志:
--Output from test sayHi--
Init HiService,test.HiService@530f5e8e
hiService is null when new User(null)
Before use hiService null
| Failure: test sayHi(test.HiServiceTest)
| java.lang.NullPointerException: Cannot invoke method sayHi() on null object
at test.User.sayHi(User.groovy:17)
at test.HiServiceTest.test sayHi(HiServiceTest.groovy:20)
服务已初始化,但无法注入域。但是当 运行 直接应用时,服务会自动注入域
如果您不想自动装配,则需要进行集成测试。如果使用 Grails 3 则使用 @Integration 注释,如果使用 grails 2 则扩展 IntegrationSpec。
参见:http://docs.grails.org/latest/guide/testing.html#integrationTesting
@Mock([User, HiService])
class HiServiceTest extends Specification {
def "test sayHi"() {
// ....
}
}
由于您正在编写单元测试,因此您的服务不会自动装配。此外,当您对 User class 对象进行单元测试时,您应该在 UserSpec 中编写测试(而不是 UserServceTest;Suffixing Spec 是 Spock 中的约定)。现在您可以像这样模拟 HiService:
class UserSpec 扩展规范 {
def "User is able to say hi"() {
given:
User user = new User(name: 'bla bla')
and: "Mock the user service"
def hiService = Mock(HiService)
user.hiService = hiService
when:
user.sayHi()
then:
1 * sayHiService.sayHi(user.name)
}
}