不能在Test行为调用的Java函数中使用Citrus变量

时间:2019-02-09 08:31:53

标签: java integration-testing citrus-framework

我想在测试中循环执行一种行为,该行为将响应通过“消息模板(文件)”生成的消息对某些请求的响应,在该消息中,我用柑橘类测试变量的值和索引的索引替换了一些字符串环。我想我几乎可以使它正常工作,但是不幸的是,当我尝试在行为中使用ReplaceAll String函数时,测试崩溃。请参阅下面的代码片段,其中删除了所有不必要的部分,以期使我的问题更容易理解

   public class myBehavior extends AbstractTestBehavior {

        private String payloadData;

        myBehavior withPayloadData(String payload) {
            this.payloadData = payload;
            return this;
        }

        @Override
        public void apply() {
            echo("[behavior] - OK ->behavior is invoked");
            echo("[behavior]" + payloadData + " - OK ->variable from Test is correctly transmitted to behavior");
            echo(func_asis(payloadData));
            echo(func_replace(payloadData));  // if you uncomment this line the test will crash at starting time when invoking replace_all
        }


        String func_asis(String myvar)
        {
          String s = "This is a string in which nothing is replaced, OK fine !";
          echo("[func_asis] OK ->in func_asis now ");
          echo("[func_asis] myvar="+ myvar + " - OK ->variable from Test is correctly transmitted to func_asis");
          return s;
        }

        String func_replace(String myvar)
        {
          String s = "This is a string in which to replace !!Name!! by the value of my citrus variable but it crashes";
          echo("[func_replace] OK ->in func_replace");
          echo("[func_replace] myvar="+ myvar + " - OK ->variable from Test is correctly transmitted to func_asis");
          //s=s.replaceAll("!!Name!!",myvar); // This will crash when starting the test (not actually when running it) !!!
          return s;
        }

    }

    @CitrusTest 
    public void mySimpleTest() throws IOException {
      description("Simple Test invoking a behavior which it self will invoke a java function");
      variable("vm", "/dc/vm/folder/vm_basename");

      repeat().until("i = 3")
            .actions(
              sleep(1000L),
              applyBehavior(new myBehavior().withPayloadData("${vm}${i}"))
            ); 
    }
  • 这是测试的输出,在func_replace中注释了replaceAll调用。
    09:21:22,102 DEBUG port.LoggingReporter| BEFORE TEST SUITE
    09:21:22,102 INFO  port.LoggingReporter| 
    09:21:22,103 INFO  port.LoggingReporter| 
    09:21:22,103 INFO  port.LoggingReporter| BEFORE TEST SUITE: SUCCESS
    09:21:22,103 INFO  port.LoggingReporter| ------------------------------------------------------------------------
    09:21:22,103 INFO  port.LoggingReporter| 
    09:21:22,119 DEBUG t.TestContextFactory| Created new test context - using global variables: '{}'
    09:21:22,128 INFO  port.LoggingReporter| 
    09:21:22,128 INFO  port.LoggingReporter| ------------------------------------------------------------------------
    09:21:22,128 DEBUG port.LoggingReporter| STARTING TEST CitrusLearning.mySimpleTest <com.grge.citrus.cmptest.stratus>
    09:21:22,128 INFO  port.LoggingReporter| 
    09:21:22,129 DEBUG      citrus.TestCase| Initializing test case
    09:21:22,130 DEBUG  context.TestContext| Setting variable: citrus.test.name with value: 'CitrusLearning.mySimpleTest'
    09:21:22,130 DEBUG  context.TestContext| Setting variable: citrus.test.package with value: 'com.grge.citrus.cmptest.stratus'
    09:21:22,130 DEBUG  context.TestContext| Setting variable: vm with value: '/dc/vm/folder/vm_basename'
    09:21:22,130 DEBUG      citrus.TestCase| Test variables:
    09:21:22,131 DEBUG      citrus.TestCase| citrus.test.name = CitrusLearning.mySimpleTest
    09:21:22,131 DEBUG      citrus.TestCase| citrus.test.package = com.grge.citrus.cmptest.stratus
    09:21:22,131 DEBUG      citrus.TestCase| vm = /dc/vm/folder/vm_basename
    09:21:22,131 INFO  port.LoggingReporter| 
    09:21:22,131 DEBUG port.LoggingReporter| TEST STEP 1/1: repeat
    09:21:22,131 DEBUG port.LoggingReporter| TEST ACTION CONTAINER with 9 embedded actions
    09:21:22,131 DEBUG  context.TestContext| Setting variable: i with value: '1'
    09:21:22,134 INFO   actions.SleepAction| Sleeping 1000 ms
    09:21:23,139 INFO   actions.SleepAction| Returning after 1000 ms
    09:21:23,139 INFO    actions.EchoAction| [behavior] - OK ->behavior is invoked
    09:21:23,139 INFO    actions.EchoAction| [behavior]/dc/vm/folder/vm_basename1 - OK ->variable from Test is correctly transmitted to behavior
    09:21:23,140 INFO    actions.EchoAction| [func_asis] OK ->in func_asis now 
    09:21:23,140 INFO    actions.EchoAction| [func_asis] myvar=/dc/vm/folder/vm_basename1 - OK ->variable from Test is correctly transmitted to func_asis
    09:21:23,140 INFO    actions.EchoAction| This is a string in which nothing is replaced, OK fine !
    09:21:23,140 INFO    actions.EchoAction| [func_replace] OK ->in func_replace
    09:21:23,141 INFO    actions.EchoAction| [func_replace] myvar=/dc/vm/folder/vm_basename1 - OK ->variable from Test is correctly transmitted to func_asis
    09:21:23,141 INFO    actions.EchoAction| This is a string in which to replace !!Name!! by the value of my citrus variable but it crashes
    09:21:23,143 DEBUG leanExpressionParser| Boolean expression 2 = 3 evaluates to false
    09:21:23,143 DEBUG  context.TestContext| Setting variable: i with value: '2'
    09:21:23,143 INFO   actions.SleepAction| Sleeping 1000 ms
    09:21:24,145 INFO   actions.SleepAction| Returning after 1000 ms
    09:21:24,145 INFO    actions.EchoAction| [behavior] - OK ->behavior is invoked
    09:21:24,145 INFO    actions.EchoAction| [behavior]/dc/vm/folder/vm_basename2 - OK ->variable from Test is correctly transmitted to behavior
    09:21:24,145 INFO    actions.EchoAction| [func_asis] OK ->in func_asis now 
    09:21:24,145 INFO    actions.EchoAction| [func_asis] myvar=/dc/vm/folder/vm_basename2 - OK ->variable from Test is correctly transmitted to func_asis
    09:21:24,145 INFO    actions.EchoAction| This is a string in which nothing is replaced, OK fine !
    09:21:24,146 INFO    actions.EchoAction| [func_replace] OK ->in func_replace
    09:21:24,146 INFO    actions.EchoAction| [func_replace] myvar=/dc/vm/folder/vm_basename2 - OK ->variable from Test is correctly transmitted to func_asis
    09:21:24,146 INFO    actions.EchoAction| This is a string in which to replace !!Name!! by the value of my citrus variable but it crashes
    09:21:24,146 DEBUG leanExpressionParser| Boolean expression 3 = 3 evaluates to true
    09:21:24,146 INFO  port.LoggingReporter| 
    09:21:24,147 DEBUG port.LoggingReporter| TEST STEP 1/1 SUCCESS
  • 这是取消注释该行时的崩溃日志。
        09:27:51,525 DEBUG port.LoggingReporter| BEFORE TEST SUITE
        09:27:51,525 INFO  port.LoggingReporter| 
        09:27:51,525 INFO  port.LoggingReporter| 
        09:27:51,525 INFO  port.LoggingReporter| BEFORE TEST SUITE: SUCCESS
        09:27:51,525 INFO  port.LoggingReporter| ------------------------------------------------------------------------
        09:27:51,525 INFO  port.LoggingReporter| 
        09:27:51,542 DEBUG t.TestContextFactory| Created new test context - using global variables: '{}'
        09:27:51,551 INFO  port.LoggingReporter| 
        09:27:51,552 ERROR port.LoggingReporter| TEST FAILED CitrusLearning.mySimpleTest <com.grge.citrus.cmptest.stratus> Nested exception is: 
        java.lang.IllegalArgumentException: No group with name {vm}
            at java.util.regex.Matcher.appendReplacement(Matcher.java:849)
            at java.util.regex.Matcher.replaceAll(Matcher.java:955)
            at java.lang.String.replaceAll(String.java:2223)
            at com.grge.citrus.cmptest.stratus.CitrusLearning$myBehavior.func_replace(CitrusLearning.java:180)
            at com.grge.citrus.cmptest.stratus.CitrusLearning$myBehavior.apply(CitrusLearning.java:163)
            at com.consol.citrus.dsl.design.AbstractTestBehavior.apply(AbstractTestBehavior.java:53)
            at com.consol.citrus.dsl.design.ApplyTestBehaviorAction.doExecute(ApplyTestBehaviorAction.java:38)
            at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42)
            at com.consol.citrus.dsl.design.DefaultTestDesigner.applyBehavior(DefaultTestDesigner.java:193)
            at com.consol.citrus.dsl.testng.TestNGCitrusTestDesigner.applyBehavior(TestNGCitrusTestDesigner.java:168)
            at com.grge.citrus.cmptest.stratus.CitrusLearning.mySimpleTest(CitrusLearning.java:194)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:216)
            at com.consol.citrus.testng.AbstractTestNGCitrusTest.invokeTestMethod(AbstractTestNGCitrusTest.java:121)
            at com.consol.citrus.dsl.testng.TestNGCitrusTest.invokeTestMethod(TestNGCitrusTest.java:121)
            at com.consol.citrus.dsl.testng.TestNGCitrusTestDesigner.invokeTestMethod(TestNGCitrusTestDesigner.java:73)
            at com.consol.citrus.dsl.testng.TestNGCitrusTest.run(TestNGCitrusTest.java:110)
            at com.consol.citrus.dsl.testng.TestNGCitrusTest.run(TestNGCitrusTest.java:56)
            at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:242)
            at org.testng.internal.Invoker.invokeMethod(Invoker.java:579)
            at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
            at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)
            at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
            at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
            at org.testng.TestRunner.privateRun(TestRunner.java:648)
            at org.testng.TestRunner.run(TestRunner.java:505)
            at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
            at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
            at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
            at org.testng.SuiteRunner.run(SuiteRunner.java:364)
            at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
            at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
            at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
            at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
            at org.testng.TestNG.runSuites(TestNG.java:1049)
            at org.testng.TestNG.run(TestNG.java:1017)
            at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:135)
            at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeSingleClass(TestNGDirectoryTestSuite.java:112)
            at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:99)
            at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:146)
            at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:373)
            at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:334)
            at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:119)
            at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:407)
        09:27:51,555 INFO  port.LoggingReporter| ------------------------------------------------------------------------
        09:27:51,555 INFO  port.LoggingReporter| 
        09:27:51,595 INFO  port.LoggingReporter| 
        09:27:51,595 INFO  port.LoggingReporter| ------------------------------------------------------------------------
        09:27:51,595 DEBUG port.LoggingReporter| AFTER TEST SUITE

对于解决这个问题有很多想法

2 个答案:

答案 0 :(得分:1)

您面临的问题是

s=s.replaceAll("!!Name!!",myvar);

不属于Java DSL测试的一部分。在测试运行之前对其进行评估。行为描述为in the Citrus documentat。但是,对echo(...)的调用是DSL的一部分,因此在实际运行测试时被执行。

您可以做的是让柑橘为您替补。您要用串联的"!!Name!!"vm的值替换i。为此,请在模板中将"!!Name!!"替换为"${vm}${i}",然后让柑橘为您完成繁重的工作:

        String func_replace(String myvar)
        {
          String s = "This is a string in which to replace ${vm}${id} by the value of my citrus variable but it crashes";
          echo("[func_replace] OK ->in func_replace");
          echo("[func_replace] myvar="+ myvar + " - OK ->variable from Test is correctly transmitted to func_asis");
          return s;
        }

Stringapply()类的myBehavior中使用返回的echo(...)时,柑橘为您代入。

答案 1 :(得分:1)

花了更多时间,我开始理解Citrus如何处理变量,在上述情况下,'myvar'的值实际上设置为“ $ {vm} $ {i}”,执行时将被替换时间,但是从测试动作中调用时...。因此,我查看了自定义测试动作,发现即使在某个时候,变量实例化也有些棘手...但是,尽管如此,我还是可以实现我想做的第一部分是用变量内容替换字符串中的一些预定义值。请参见下面的代码片段。

...但是现在因为我从一个动作中调用了replace函数,所以我无法将字符串返回给调用者,而这正是我打算在行为中执行的操作...因此,我们将调查这是否可行以及如何实现。看看我的测试的其他设计(例如临时文件,其中存储有替换值的字符串,该替换值在func_replace将更新它们后被行为读取。) 无论如何,这是我上面遇到的问题的解决方案:


@Test
public class CitrusLearningL4 extends TestNGCitrusTestDesigner {

    public class myBehavior extends AbstractTestBehavior {

        private @CitrusResource TestContext parentContext;        

        myBehavior withContext(@Optional @CitrusResource TestContext context) {
            this.parentContext=context;
            return this;
        }

        @Override
        public void apply() {
            echo("[behavior] - OK ->behavior is invoked");
            func_replace();
            echo("[behavior] - OK ->behavior is finished");

        }

        void func_replace()
        {
          final String s = "This is a string in which '!!Name!!' is present because it was replaced by the value of my test variable";
          echo("[func_replace] OK ->in func_replace");
          action(new AbstractTestAction() {
                public void doExecute(TestContext context) {
                  String s1 = s;
                  System.out.println("[anAction] - OK ->anAction is invoked"); 
                  String sVar=String.format("%s", (String) parentContext.getVariable("vm") + (String) parentContext.getVariable("i"));
                  System.out.println("[anAction] - OK ->" + s1.replaceAll("!!Name!!",sVar));      
                }
              });         
        }

    }

    @Test @Parameters("context")
    @CitrusTest 
    public void mySimpleBehaviorTest(@Optional @CitrusResource TestContext context) throws IOException {
      description("Simple Test invoking a behavior which it self will invoke a java function");
      variable("vm", "/dc/vm/folder/vm_basename");

      repeat().until("i = 3")
            .actions(
              sleep(1000L),
              applyBehavior(new myBehavior().withContext(context))
            ); 
    }

}