Grails 模拟服务调用时出错

Grails 模拟服务调用时出错,grails,service,spock,integration-testing,Grails,Service,Spock,Integration Testing,错误发生在服务的集成测试上。是的,我们目前正在对我们的服务进行集成测试,作为一种解决方法,因为由于用户类型映射,我们无法通过单元测试来测试服务 关于用户类型:我们的域使用接口作为属性。此外,findByinterface在grails上不起作用 见下文: class Domain { SomeProperty someProperty String otherProperty } public interface SomeProperty { //methods }

错误发生在服务的集成测试上。是的,我们目前正在对我们的服务进行集成测试,作为一种解决方法,因为由于用户类型映射,我们无法通过单元测试来测试服务

关于用户类型:我们的域使用接口作为属性。此外,findByinterface在grails上不起作用

见下文:

class Domain {
    SomeProperty someProperty
    String otherProperty
}

public interface SomeProperty {
    //methods
}

enum Enum implements SomeProperty {
    NAME,
    OTHERNAME

    //implementation of methods
}
类域可以处理实现SomeProperty接口的不同类型的枚举。 数据库不知道应该保存什么特定值,所以我们使用userType。下面是具有映射的域

class Domain {
    SomeProperty someProperty
    String otherProperty
}

static mapping = {
    id generator: 'sequence', column: 'id', params: [sequence: 'domain_sequence']
    someProperty type : userType, {
        column name: "someProperty", sqlType: "varchar", length: 255
    }
}
更新:

正在测试的代码:

class ServiceBeingTested {

AnotherServiceInsideServiceBeingTested anotherServiceInsideServiceBeingTested //or def anotherServiceInsideServiceBeingTested

    public void methodBeingTested(param1, param2, param3) {

        Object object = privateMethod(..., ...) //private method contains no other service calls. just pure logic
        anotherServiceInsideServiceBeingTested.voidMethod1(....)
        anotherServiceInsideServiceBeingTested.voidMethod2(....)

    }
}
我的集成测试:

class ServiceBeingTestedIntegrationSpec extends IntegrationSpec {

ServiceBeingTested serviceBeingTested = new ServiceBeingTested()
AnotherServiceInsideServiceBeingTested anotherServiceInsideServiceBeingTested   

    void setUp () {
        anotherServiceInsideServiceBeingTested = Mock()
        serviceBeingTested.anotherServiceInsideServiceBeingTested = anotherServiceInsideServiceBeingTested
    }

    void cleanup () {
        //code here
    }

    void "methodBeingTested should invoke the 2 service method call"() {
        given:
        //initialize data here
        //code

        when:
        serviceBeingTested.methodBeingTested(param1, param2, param3)

        then:
        1 * anotherServiceInsideServiceBeingTested.voidMethod1(....)
        1 * anotherServiceInsideServiceBeingTested.voidMethod2(....)
    }
}
堆栈跟踪:

|  Too few invocations for:
1 * anotherServiceInsideServiceBeingTested.voidMethod2(....)   (0 invocations)
Unmatched invocations (ordered by similarity):
1 * anotherServiceInsideServiceBeingTested.this$3$voidMethod2(....)
正确调用了另一个与另一个ServiceInsideServiceBeingTested相同的服务调用,即另一个ServiceInsideServiceBeingTested.voidMethod1。我尝试将测试voidMethod2中的参数更改为通配符,但仍然会导致此错误


在集成测试用例中,您不需要模拟任何服务,因为在加载完整的应用程序时,这些服务在默认情况下是可用的。 尽管在单元测试中,您可以使用@TestFor注释并指定要测试的服务,但这将注入一个服务变量,该变量将通过您的规范/测试类可用

@TestFor(Service)
class ServiceBeingTestedIntegrationSpec extends Specification {

ServiceBeingTested serviceBeingTested = new ServiceBeingTested()   

    void setUp () {
        serviceBeingTested.service = service
    }

    void cleanup () {
        //code here
    }

    void "methodBeingTested should invoke the 2 service method call"() {
        given:
        //initialize data here
        //code

        when:
        serviceBeingTested.methodBeingTested(param1, param2, param3)

        then:
        1 * service.voidMethod1(....)
        1 * service.voidMethod2(....)
    }
}
此外,在上述情况下,您还可以尝试在模拟这些方法后在安装程序中存根您的方法,以避免您的服务调用的任何其他服务,这些服务将引发NullPointerException,并且最终在单元测试的情况下,您的测试将失败

存根的示例可以是:

1*service.voidMethod1 >> {
      //some code setting up any data for you.
}


1*service.voidMethod2 >> {
      //some code setting up any data for you.
}

如果您像上面那样使用stubing,您也可以简单地写下单元测试用例。

只是为了添加。注意到我们在模仿其他服务调用,而不是让它执行实际void方法所做的操作,这是因为单元测试无法处理域模型的用户类型映射,我们希望对其进行单元测试。因此,单元测试的测试风格的相同行为只是通过集成测试specmind,如果有人可以评论为什么否决?如果有必要,我会更新这个问题。TNX什么是服务变量?您所谈论的用户类型关系是什么。请用这些细节编辑/更新你的帖子。只是为了澄清这个问题。方法voidMethod2一直是一个私有方法。正在测试另一个服务。此$3$voidMethod2(..)表示歉意,我不确定我是否正确理解了上面的答案。但是在我们的例子中,我们不能使用单元测试,因为用户类型在该环境中不起作用——因此集成测试是一种解决方法,但其行为有点像单元测试(模仿其他服务调用)。至于测试,我希望确保调用voidMethod1和voidMethod2,而不管这些方法将做什么。此外,我认为服务调用交互测试不会返回空指针。不过我不确定。谢谢你抽出时间。经过一个小时的复查。voidMethod2是我想要检查调用的服务的私有方法。我应该知道stacktrace的“这个”:)谢谢。我真丢脸:))