在gpars activeobject方法

时间:2016-03-08 13:55:43

标签: unit-testing groovy spock gpars active-objects

我一直试图做一些测试并且无法弄清楚问题是什么

在我的代码中我有两个类,一个名为DynamicRule,另一个名为AORule,它为规则实例提供了一个GPARS activeObject包装器。

DynamicRule看起来有点像这样 - 使用名为dynamicExecute

的方法
@InheritConstructors
@Component
@Slf4j  //use Groovy AST to get logger
@EqualsAndHashCode
@Scope ("prototype")       //IOC to deliver new instance on each injection
@Qualifier ("dynamicRule")

class DynamicRule extends BasicRule implements org.easyrules.api.Rule {

    Closure dynamicEvaluation = null
    Closure dynamicExecution = null
    String  sync = "sync"
... with method 
void dynamicExecute () {
    log.debug "dynamic execute: " + this.dump() +  " : dynamic execute called : a rule.dynamicExecution was defined as > " + this.dynamicExecution
    //if dynamic execution closure defined then call that
    log.debug "dynamic execute: getting DynamicExecution reference "
    def clos = this.getDynamicExecution()
    //assert clos == this.dynamicExecution
    log.debug "dynamic execute: rule.dynamicExecution using get() returns " + clos.dump()
    if (clos) {
        clos.call()  //call execute action
        log.debug "dynamic execute: dynamic rule closure  was executed "
    }
}....

我有一个这个AORule的包装器类,它使用GPARS activeObject来管理这样的DynamicRule rule引用状态,其中execute()方法调用异步activeObject方法来触发内部{ {1}}参考

rule

我一直在尝试编写一些测试来证明这对我自己有用,但它失败了。我试图做一个两个简单的测试,一个用于dynamicRule本身就可以工作 - 我设置了期望并要求Mock调用一个闭包并测试该闭包对@Component @Scope("prototype") @ActiveObject @Slf4j @EqualsAndHashCode class AORule implements org.easyrules.api.Rule { //setup delegate dynamicRule and make it a part of this ActiveObject //prototyped setter injection //@Autowired //@Scope ("prototype") //@Qualifier ("dynamicRule") @Delegate DynamicRule rule AORule (name, description=null) { log.debug "Create aorule.rule name/desc constructor called " rule = new DynamicRule (name, description ?: "Basic Active Object Rule") } AORule () { log.debug "Create aorule.rule default constructor called " rule = new DynamicRule () } @Autowired (/*required=true*/) AORule (@Qualifier ("dynamicRule") DynamicRule dynrule) { log.debug "Create aorule.rule injected rule constructor called " rule = dynrule } .... void execute () { active_execute() } /** * Active method manages async action through object inside through hidden actor. * variable 'rule' is the variable we are protecting. Runs either any dynmicExecution closure * where defined or just runs the standard class execute method * * @return void */ @ActiveMethod void active_execute () { //rule.execute() log.debug "activeExec : rule dump looks like " + rule.dump() def val = rule.dynamicExecution assert val == true log.debug "activeExec : ret value of rule.getDynamicExecution() was > " + val if (val != null) { log.debug "activeExec : running dynamicExecution closure, where rule closure was " + rule?.dynamicExecution.toString() rule.dynamicExecute() //should call method that executes closure, where this is defined } else { log.debug "activeExec : running std Execution action " rule.execute() } } 变量的副作用 - 一切正常预期

mockres

在我的第二次测试中,我设置了Mock并将其设置在aorule.rule实例上并设置了模拟的期望,调用def "set execution closure using spock mock but call stub directly when doing an execute action " () { given:"setup of stub for testing " def mockres = "" def clos = { mockres = "did nothing"; println "script: in stub closure, setting mockres to " + mockres + " mockres dump > " + mockres.dump(); } //spock mock DynamicRule stub = Mock () 1*stub.dynamicExecute() >> {clos()} // pretend this has been set when : "execution on stub directly " stub.dynamicExecute() then : "test execute closure ran as expected " mockres == "did nothing" } 方法调用aorule.execute()活动方法,调用我的模拟

activeExecute()

这失败了 - 为什么关闭不在mock上运行,然后:断言测试失败

我在这里包含了部分输出跟踪 - 你可以看到def "set execution closure using spock mock but call aorule.execute() when doing an execute action " () { given:"setup of stub for testing " def mockres = "" def clos = { mockres = "did nothing"; println "script: in stub closure, setting mockres to " + mockres + " mockres dump > " + mockres.dump(); } //spock mock DynamicRule stub = Mock () 1*stub.getDynamicExecution() >> { true } 1*stub.dynamicExecute() >> {clos()} // pretend this has been set println "test: save stub on aorule" aorule.rule = stub when : "call execute() on aorule.rule for stub " //stub.dynamicExecute() //aorule.rule.dynamicExecute() //works println "test: call aorule.execute" aorule.execute() //think this must be getting a new prototype object which is why not getting called then : "test execute closure ran as expected " mockres == "did nothing" } 触发了activeObject方法,我可以看到aorule.execute()的日志跟踪 - 但是之后它似乎都是停止,没有额外的跟踪输出(我希望看到val的值例如),并且没有调用存根闭包并且没有设置mockres - 测试失败

activeExec : rule dump looks like

我一直围着房子试图追踪这个,或者在调试器中观看无济于事。我的存根闭包未被触发 - 测试失败。

我刚刚尝试再次在调试器中观看,当我走过这条线时

...
test: save stub on aorule
13:07:45.361 [main] DEBUG org.easyrules.spring.AORule - setting aorule.rule with > Mock for type 'DynamicRule' named 'stub'
test: call aorule.execute
13:07:45.367 [Actor Thread 1] DEBUG org.easyrules.spring.AORule - activeExec : rule dump looks like   <org.easyrules.spring.DynamicRule$$EnhancerByCGLIB$$9b33215e@a4770a4 CGLIB$BOUND=false CGLIB$CALLBACK_0=org.spockframework.mock.runtime.CglibMockInterceptorAdapter@4809f9c CGLIB$CALLBACK_1=net.sf.cglib.proxy.NoOp$1@bf1bd4 dynamicEvaluation=null dynamicExecution=null sync=null name=null description=null priority=0>
13:07:45.441 [main] DEBUG o.s.t.c.s.AbstractDirtiesContextTestExecutionListener - After test method: context [DefaultTestContext@5c6648b0 testClass = AORuleSpecTest2, testInstance = org.easyrules.spring.AORuleSpecTest2@d41f816, testMethod = $spock_feature_0_1@AORuleSpecTest2, testException = Condition not satisfied:

mockres == "did nothing"
|       |
""      false
        11 differences (0% similarity)
        (-----------)
        (did nothing)
, mergedContextConfiguration = [MergedContextConfiguration@6f1de4c7 testClass = AORuleSpecTest2, locations = '{}', classes = '{class org.easyrules.spring.AORule, class org.easyrules.spring.DynamicRule}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].

Condition not satisfied:

调试器跳转到GPAR中某处的 def val = rule.dynamicExecution 错误处理程序。如果我将其更改为

,则会产生差异
InternalActor.handleCurrentMessage()

我没有得到这个我做的事情愚蠢/愚蠢不确定但我不能为我的 def val = rule.getDynamicExecution() //try to get value via groovy auo method 编写测试使用Mocks测试代码(我试图通过手工制作的课程等来做到这一点,但不能让模拟测试工作。

任何人都有任何想法我做错了什么以及如何正确地纠正和运行测试。据我所知 - 当我在脚本中运行代码('实时'测试)时,代码看起来像我想做的那样,但我不能进行单元测试来显示

后记:它与ActiveMethod包装有关 - 不确定是什么

我在测试脚本中创建了两个dummay包装类,如下所示 - 一个没有ActiveObject,另一个有ActiveObject支持 - 都在嵌入式规则上调用@ActiveMethod - activeExecute()方法。 AOWrappers是dynamicExecute()

@ActiveMethod

同一个脚本文件中的两个测试看起来

class WrapperRule {
    @Autowired   //property injection
    @Delegate DynamicRule rule

    WrapperRule () {

    }

    WrapperRule (DynamicRule irule) {
        rule = irule
        assert rule
    }

    void execute () {
        rule.dynamicExecute()
    }

}

@ActiveObject
@Slf4j
@EqualsAndHashCode
class AOWrapperRule {
    @Autowired   //property injection
    @Delegate DynamicRule rule

    AOWrapperRule () {

    }

    AOWrapperRule (DynamicRule irule) {
        rule = irule
        assert rule
    }

    @ActiveMethod
    void execute () {
        rule.dynamicExecute()
    }

}

当我运行测试时 - 第一个传递正常,第二个失败并且我的clos没有被调用。谁知道我接下来要做什么?

附录/澄清问题 - 10-3-2016

我已经尝试并将其简化为单个groovy测试文件 - 正在测试的类和同一文件中的测试,以便您可以希望看到正在发生的事情

def "set execution closure using spock mock  on simple Wrapper rule  when doing an execute action " () {

    given:"setup of stub for testing "

    def mockres = ""

    def clos = {
        mockres = "did nothing";
        println "script: in stub closure, setting mockres to  " + mockres + " mockres dump > " + mockres.dump();
    }

    WrapperRule wrule = new WrapperRule ()

    //spock mock
    DynamicRule stub =  Mock  ()
    1*stub.dynamicExecute() >> {clos()}  // pretend this has been set

    println "test: save stub on wrule"
    wrule.rule = stub

    when : "call execute() on wrule.rule for stub   "

    println "test: call wrule.execute"
    wrule.execute()   //think this must be getting a new prototype object which is why not getting called

    then : "test execute closure ran as expected "
    mockres == "did nothing"

}

def "set execution closure using spock mock  on AO Wrapper rule  when doing an execute action " () {

    given:"setup of stub for testing "

    def mockres = ""

    def clos = {
        mockres = "did nothing";
        println "script: in stub closure, setting mockres to  " + mockres + " mockres dump > " + mockres.dump();
    }

    AOWrapperRule aowrule = new AOWrapperRule ()

    //spock mock
    DynamicRule stub =  Mock  ()
    1*stub.dynamicExecute() >> {clos()}  // pretend this has been set

    println "test: save stub on aowrapper"
    aowrule.rule = stub

    when : "call execute() on aowrule.rule for stub   "

    println "test: call aowrule.execute"
    aowrule.execute()   //think this must be getting a new prototype object which is why not getting called

    then : "test execute closure ran as expected "
    mockres == "did nothing"

}

要注意的关键点是最后一次测试。我在Mock上设置期望来运行闭包输出,这将更新package org.easyrules.spring import groovy.mock.interceptor.StubFor import groovy.transform.EqualsAndHashCode import groovy.util.logging.Slf4j import groovyx.gpars.activeobject.ActiveMethod import groovyx.gpars.activeobject.ActiveObject import org.junit.runner.RunWith import org.softwood.RulesApplication import org.springframework.beans.factory.annotation.Autowire import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration import org.springframework.context.ApplicationContext import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.junit4.SpringJUnit4ClassRunner import spock.lang.Specification import spock.lang.Unroll import spock.lang.* /** * Created by William on 10/03/2016. */ class TestRule { Closure dynamicExecute = {println "default rule Execution "} def exec () { dynamicExecute() } } class TestWrapperRule { @Delegate TestRule rule TestWrapperRule () { rule = new TestRule() } void execute () { rule.exec() } } @ActiveObject @Slf4j @EqualsAndHashCode class TestAOWrapperRule { @Delegate TestRule rule TestAOWrapperRule () { rule = new TestRule() } @ActiveMethod void execute () { rule.exec() } } class AORuleSpecAllInOneSpecTest extends Specification { def "test simple closure setting mockres value - basics " () { given: def mockres = "" def clos = { mockres = "did nothing"; println "script: in stub closure, setting mockres to " + mockres + " mockres dump > " + mockres.dump(); } when: clos() //call closure then: "test mockres was set when closure called " mockres == "did nothing" } def "set execution closure using spock mock on simple Wrapper rule when doing an execute action " () { given:"setup of stub for testing " def mockres = "" def clos = { mockres = "did nothing"; println "script: in stub closure, setting mockres to " + mockres + " mockres dump > " + mockres.dump(); } TestWrapperRule wrule = new TestWrapperRule () //spock mock TestRule stub = Mock () //1*stub.exec() >> {clos()} // pretend this has been set 1*stub.getDynamicExecute() >> {clos()} // pretend this has been set println "test: save stub on wrule" wrule.rule = stub when : "call execute() on wrule.rule for stub " println "test: call wrule.execute" //wrule.exec() wrule.dynamicExecute then : "test execute closure ran as expected " mockres == "did nothing" } def "set execution closure using spock mock on AO Wrapper rule when doing an execute action " () { given:"setup of stub for testing " def mockres = "" def clos = { mockres = "did nothing"; println "script: in stub closure, setting mockres to " + mockres + " mockres dump > " + mockres.dump(); } TestAOWrapperRule aowrule = new TestAOWrapperRule () //spock mock TestRule stub = Mock () stub.exec() >> {clos()} // pretend this has been set println "test: save stub on aowrapper" aowrule.rule = stub when : "call execute() on aowrule.rule for stub " println "test: call aowrule.execute" aowrule.execute() //aowrule.exec() //if you then call the @delegate func without the activeMethod the test will work then : "test execute closure ran as expected " mockres == "did nothing" } } 变量,我可以在then:子句中设置断言。

当你致电mockres时,测试会像这样失败

@ActiveMethod execute()

表明mockres没有被闭包调用设置。

如果取消注释后面的aowrule.exec()行,则会直接调用委托的...script: in stub closure, setting mockres to did nothing mockres dump > <java.lang.String@c141192c value=did nothing hash=-1052698324> Condition not satisfied: mockres == "did nothing" | | "" false 11 differences (0% similarity) (-----------) (did nothing) 调用 - 不使用ActiveMethod使用的隐藏actor。当你运行下一行时,正确调用闭包并设置mockres。

所以问题有一些事情要做,试图通过exec()后面隐藏的演员来测试模拟是否有效。

我认为实际上代码正在做我期望的,如果只是作为脚本运行(在代码中真正使用)。但是,我似乎无法编写测试,证明调用ActiveMethod时的预期行为。

我是否必须做一些聪明的事情来为Mocks编写针对异步代码(如GPAR)的spock测试 - 或者这是应该有效的但不是。我希望能为你澄清我的问题

0 个答案:

没有答案