【问题标题】:Grails Can't inject service to domain when test with Spock使用 Spock 进行测试时,Grails 无法将服务注入域
【发布时间】:2017-01-07 09:50:37
【问题描述】:

使用 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)

服务已初始化,但无法注入域。但是当直接运行应用程序时,服务会自动注入到域中

【问题讨论】:

  • 你需要 item.hiService = servicegiven: 块中。
  • @dmahapatro 成功了,谢谢
  • @dmahapatro 在进行单元测试时手动在域中初始化服务不是很方便,因为每个域可能使用多个服务,而我们可能在每个单元测试中使用多个域,所以你有什么想法解决这个问题?
  • 改写集成测试,正如 Hoof 在他的回答中提到的那样。
  • 学到了很多。谢谢。 ^+^

标签: grails service dns spock inject


【解决方案1】:

如果您不想自动装配,则需要进行集成测试。如果使用 Grails 3,则使用 @Integration 进行注释,如果使用 grails 2,则扩展 IntegrationSpec。

见:http://docs.grails.org/latest/guide/testing.html#integrationTesting

【讨论】:

    【解决方案2】:

    @Mock([User, HiService])
    class HiServiceTest extends Specification {
    
        def "test sayHi"() {
            // ....
        }
    }

    【讨论】:

      【解决方案3】:

      由于您正在编写单元测试,因此您的服务不会自动装配。此外,当您对 User 类对象进行单元测试时,您应该在 UserSpec 中编写测试(而不是 UserServceTest;后缀 Spec 是 Spock 中的约定)。现在您可以像这样模拟 HiService:

      类 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)
      }
      

      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-05
        • 1970-01-01
        • 2013-09-09
        • 2012-03-29
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多