【问题标题】:Error in mocking service invocation模拟服务调用时出错
【发布时间】:2015-12-10 02:44:57
【问题描述】:

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

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

见下文:

class Domain {
    SomeProperty someProperty
    String otherProperty
}

public interface SomeProperty {
    //methods
}

enum Enum implements SomeProperty {
    NAME,
    OTHERNAME

    //implementation of methods
}

class Domain 可以处理实现 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(....)

另一个服务调用具有相同的 anotherServiceInsideServiceBeingTested -即 anotherServiceInsideServiceBeingTested.voidMethod1 被正确调用。我尝试将 voidMethod2 的测试参数更改为通配符,但仍然会导致此错误。

谢谢

【问题讨论】:

  • 只是为了添加。注意到我们在模拟其他服务调用,而不是让它执行实际的 void 方法所做的事情,这是因为单元测试无法处理我们的域模型的 userType 映射,我们想对其进行单元测试。因此,单元测试的测试风格相同,但只是通过集成测试规范
  • 介意是否有人可以评论为什么投反对票?如有必要,我会更新问题。 tnx
  • 什么是服务变量?以及您在谈论的 userType 关系是什么。请使用这些详细信息编辑/更新您的帖子。
  • 只是为了澄清这个问题。方法 voidMethod2 一直是私有方法。 anotherServiceInsideServiceBeingTested.this$3$voidMethod2(....)

标签: grails service spock integration-testing


【解决方案1】:

在集成测试用例中,您不需要模拟任何服务,因为这些服务在加载完整应用程序时默认可用。 虽然,在单元测试中,您可以使用 @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(....)
    }
}

此外,在上述情况下,您还可以在模拟这些方法后尝试在 setup 中存根您的方法,以避免您的服务调用的任何其他服务将抛出 NullPointerException 并最终在单元测试的情况下您的测试将失败。

存根的例子可能是:

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


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

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

【讨论】:

  • 抱歉,我不确定我是否正确理解了您的回答。但在我们的案例中,我们不能使用单元测试,因为 userTypes 无法在该环境中工作 - 因此集成测试作为一种解决方法,但在某种程度上类似于单元测试(模拟其他服务调用)。至于测试,我想确保调用 voidMethod1 和 voidMethod2 而不管这些方法会做什么。此外,我认为服务调用交互测试不会返回空指针。不过不确定。谢谢
  • 感谢您的宝贵时间。经过一个小时的复查。 voidMethod2 是我想检查调用的服务的私有方法。我应该知道堆栈跟踪“this” :) 谢谢。真丢脸:))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-22
  • 2017-07-01
  • 1970-01-01
  • 2012-07-13
相关资源
最近更新 更多