单元测试中的 Grails Spock 模拟注入服务

Grails Spock Mock Injected Service in Unit Test

如何使用 Spock 在 Grails 单元测试(规范)中注入另一个服务?

class ServiceOne {

   ServiceTwo serviceTwo

    ModelOne getMethodOne(String name) {
       // do somethings here
       return serviceTwo.getMethodTwo(name)
    }
}

class ServiceTwo {

   ServiceTwo serviceTwo

    ModelOne getMethodTwo(String name) {
       // do somethings here
       return ModelOne.get(name)
    }
}

// Tests
import grails.test.mixin.Mock
import grails.test.mixin.TestFor
import spock.lang.Specification
/**
 * Tests for ServiceOne
 */
@TestFor(ServiceOne)
@Mock(ModelOne)
class ServiceOneSpec extends Specification {
/** Inject serviceTwo in here
    Otherwise the following exception is thrown
    java.lang.NullPointerException: Cannot invoke method getMethodTwo() on null object
*/

void "test method one"() {

    when:
    ModelOne modelOne = service.getMethodOne(name)

    then:
    modelOne != null
   }
}

我没想到,这应该可以帮助您入门。

@TestFor(ServiceOne)
@Mock(ModelOne)
class ServiceOneSpec extends Specification {

   void "test method one"() {
      given:
         def mockServiceTwo = mockFor(ServiceTwo)
         // expect that getMethodTwo is called once
         mockServiceTwo.demand.getMethodTwo(1) { String name ->
            // for any arbitrary name value, return a new ModelOne
            return new ModelOne()
         }
         service.serviceTwo = mockServiceTwo.createMock()
      when:
         ModelOne modelOne = service.getMethodOne(name)

      then:
         modelOne != null
   }
}

这就是我解决问题的方法 - 通过创建一个服务对象(它不是单例但没问题,因为它只是用于单元测试)

// Test Spec
import grails.test.mixin.Mock
import grails.test.mixin.TestFor
import spock.lang.Specification
/**
 * Tests for ServiceOne
 */
@TestFor(ServiceOne)
@Mock(ModelOne)
class ServiceOneSpec extends Specification {

    @Shared ModelOne modelOne
    def setup() {
        // the magic
        service.serviceTwo = new ServiceTwo()
        modelOne = service.serviceTwo.getMethodTwo("Name")
    }

    void "test method one"() {

        when:
        ModelOne modelOne = service.getMethodOne(name)

        then:
        modelOne != null
   }
}