This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch CAMEL-26133-robotframework-null-values in repository https://gitbox.apache.org/repos/asf/camel.git
commit de49af196e0f830695fa7a7d213854ab8b0f694b Author: Claus Ibsen <[email protected]> AuthorDate: Mon Nov 2 16:56:25 2026 +0100 CAMEL-26133: camel-robotframework - skip null body, header, variable and property values The robot variables were built with mandatoryConvertTo for the body and every header, variable and property, so a null value failed the exchange. The consumer polls with an empty exchange, so every poll failed and no test ever ran. Null values are now not passed (a Robot variable cannot be null), and the test can give them a default in its own variable table. A nested map also added its first entry twice, and an empty nested map added a variable without a value; the map walk is rewritten to add each entry once. The doc examples compared the values with Should Be True, which evaluates the body and headers as Python; they now use Should Be Equal, with a note on it. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../camel/catalog/components/robotframework.json | 2 +- .../catalog/docs/robotframework-component.adoc | 24 +++++++--- .../component/robotframework/robotframework.json | 2 +- .../src/main/docs/robotframework-component.adoc | 24 +++++++--- .../robotframework/RobotFrameworkCamelUtils.java | 48 +++++++++----------- .../robotframework/RobotFrameworkEndpoint.java | 2 +- .../RobotFrameworkCamelUtilsTest.java | 46 +++++++++++++++++++ .../RobotFrameworkComponentTest.java | 24 ++++++++++ .../robotframework/RobotFrameworkConsumerTest.java | 52 ++++++++++++++++++++++ .../set_variable_camel_no_body.robot | 27 +++++++++++ 10 files changed, 208 insertions(+), 43 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/robotframework.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/robotframework.json index fd53b52ec4b1..cc4d83de861c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/robotframework.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/robotframework.json @@ -83,7 +83,7 @@ }, "bodyTypes": { "consumerOut": { "carriers": [ "null" ], "description": "No body: each poll runs the test, and the outcome is in the CamelRobotReturnCode header (0 when all tests pass)" }, - "producerIn": { "carriers": [ "any" ], "description": "The test gets the body converted to a String as the body variable, and the headers and exchange properties as headers.name and properties.name; a null body or header value fails the exchange" }, + "producerIn": { "carriers": [ "any" ], "description": "The test gets the body converted to a String as the body variable, and the headers and exchange properties as headers.name and properties.name; a null body, header or property is not passed" }, "producerOut": { "carriers": [ "unchanged" ], "description": "The body is left as it is. The CamelRobotReturnCode header has the return code of the run (0 when all tests pass, non-zero otherwise), and CamelRobotVariables the variables passed to it; a failed test does not fail the exchange" } }, "properties": { diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/robotframework-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/robotframework-component.adoc index 69a394ca886f..bd4efb6738af 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/robotframework-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/robotframework-component.adoc @@ -123,7 +123,7 @@ And the `template.robot` file: *** Test Cases *** Set Variable Camel Body Test Case ${myvar} = Set Variable ${body} - Should Be True ${myvar} == ${body} + Should Be Equal ${myvar} ${body} ---- ._Java-only: dynamic template via header_ @@ -142,26 +142,36 @@ And the `template.robot` file: *** Test Cases *** Set Variable Camel Header Test Case ${myvar} = Set Variable ${headers.testHeader} - Should Be True ${myvar} == ${headers.testHeader} + Should Be Equal ${myvar} ${headers.testHeader} ---- ._Java-only: dynamic template via header_ [source,java] ---- from("direct:in") - .setProperty"testProperty", constant("testPropertyValue")) + .setProperty("testProperty", constant("testPropertyValue")) .setHeader("CamelRobotResourceUri").constant("path/to/my/template.robot") - .to("robotframework:dummy?allowTemplateFromHeader=true"); + .to("robotframework:dummy?allowTemplateFromHeader=true&allowContextMapAll=true"); ---- And the `template.robot` file: [source,text] ---- *** Test Cases *** - Set Variable Camel Header Test Case + Set Variable Camel Property Test Case ${myvar} = Set Variable ${properties.testProperty} - Should Be True ${myvar} == ${properties.testProperty} + Should Be Equal ${myvar} ${properties.testProperty} ---- Please note that when you pass values through Camel Exchange to test cases, -they will be available as case-sensitive ``body``, ``headers.[yourHeaderName]`` and ``properties.[yourPropertyName]`` +they will be available as case-sensitive ``body``, ``headers.[yourHeaderName]``, ``variables.[yourVariableName]`` +and ``properties.[yourPropertyName]``. The exchange properties are only passed when `allowContextMapAll=true`. + +The values are passed as strings. A `null` body, header, variable or property is not passed at all, as a Robot +Framework variable cannot be `null`. So with no message body (such as the consumer, which polls with an empty +exchange), there is no `${body}` variable. A test can give such a variable a default value in its own +`*** Variables ***` table, as the values passed from Camel override that table. + +IMPORTANT: Compare the values as strings, for example with `Should Be Equal`. Do not put them into an expression that +Robot Framework evaluates as Python, such as `Should Be True` or `Evaluate`, as the message body and headers may come +from an untrusted sender. diff --git a/components/camel-robotframework/src/generated/resources/META-INF/org/apache/camel/component/robotframework/robotframework.json b/components/camel-robotframework/src/generated/resources/META-INF/org/apache/camel/component/robotframework/robotframework.json index fd53b52ec4b1..cc4d83de861c 100644 --- a/components/camel-robotframework/src/generated/resources/META-INF/org/apache/camel/component/robotframework/robotframework.json +++ b/components/camel-robotframework/src/generated/resources/META-INF/org/apache/camel/component/robotframework/robotframework.json @@ -83,7 +83,7 @@ }, "bodyTypes": { "consumerOut": { "carriers": [ "null" ], "description": "No body: each poll runs the test, and the outcome is in the CamelRobotReturnCode header (0 when all tests pass)" }, - "producerIn": { "carriers": [ "any" ], "description": "The test gets the body converted to a String as the body variable, and the headers and exchange properties as headers.name and properties.name; a null body or header value fails the exchange" }, + "producerIn": { "carriers": [ "any" ], "description": "The test gets the body converted to a String as the body variable, and the headers and exchange properties as headers.name and properties.name; a null body, header or property is not passed" }, "producerOut": { "carriers": [ "unchanged" ], "description": "The body is left as it is. The CamelRobotReturnCode header has the return code of the run (0 when all tests pass, non-zero otherwise), and CamelRobotVariables the variables passed to it; a failed test does not fail the exchange" } }, "properties": { diff --git a/components/camel-robotframework/src/main/docs/robotframework-component.adoc b/components/camel-robotframework/src/main/docs/robotframework-component.adoc index 69a394ca886f..bd4efb6738af 100644 --- a/components/camel-robotframework/src/main/docs/robotframework-component.adoc +++ b/components/camel-robotframework/src/main/docs/robotframework-component.adoc @@ -123,7 +123,7 @@ And the `template.robot` file: *** Test Cases *** Set Variable Camel Body Test Case ${myvar} = Set Variable ${body} - Should Be True ${myvar} == ${body} + Should Be Equal ${myvar} ${body} ---- ._Java-only: dynamic template via header_ @@ -142,26 +142,36 @@ And the `template.robot` file: *** Test Cases *** Set Variable Camel Header Test Case ${myvar} = Set Variable ${headers.testHeader} - Should Be True ${myvar} == ${headers.testHeader} + Should Be Equal ${myvar} ${headers.testHeader} ---- ._Java-only: dynamic template via header_ [source,java] ---- from("direct:in") - .setProperty"testProperty", constant("testPropertyValue")) + .setProperty("testProperty", constant("testPropertyValue")) .setHeader("CamelRobotResourceUri").constant("path/to/my/template.robot") - .to("robotframework:dummy?allowTemplateFromHeader=true"); + .to("robotframework:dummy?allowTemplateFromHeader=true&allowContextMapAll=true"); ---- And the `template.robot` file: [source,text] ---- *** Test Cases *** - Set Variable Camel Header Test Case + Set Variable Camel Property Test Case ${myvar} = Set Variable ${properties.testProperty} - Should Be True ${myvar} == ${properties.testProperty} + Should Be Equal ${myvar} ${properties.testProperty} ---- Please note that when you pass values through Camel Exchange to test cases, -they will be available as case-sensitive ``body``, ``headers.[yourHeaderName]`` and ``properties.[yourPropertyName]`` +they will be available as case-sensitive ``body``, ``headers.[yourHeaderName]``, ``variables.[yourVariableName]`` +and ``properties.[yourPropertyName]``. The exchange properties are only passed when `allowContextMapAll=true`. + +The values are passed as strings. A `null` body, header, variable or property is not passed at all, as a Robot +Framework variable cannot be `null`. So with no message body (such as the consumer, which polls with an empty +exchange), there is no `${body}` variable. A test can give such a variable a default value in its own +`*** Variables ***` table, as the values passed from Camel override that table. + +IMPORTANT: Compare the values as strings, for example with `Should Be Equal`. Do not put them into an expression that +Robot Framework evaluates as Python, such as `Should Be True` or `Evaluate`, as the message body and headers may come +from an untrusted sender. diff --git a/components/camel-robotframework/src/main/java/org/apache/camel/component/robotframework/RobotFrameworkCamelUtils.java b/components/camel-robotframework/src/main/java/org/apache/camel/component/robotframework/RobotFrameworkCamelUtils.java index d6b6da290f50..98bb50da3387 100644 --- a/components/camel-robotframework/src/main/java/org/apache/camel/component/robotframework/RobotFrameworkCamelUtils.java +++ b/components/camel-robotframework/src/main/java/org/apache/camel/component/robotframework/RobotFrameworkCamelUtils.java @@ -49,6 +49,10 @@ public final class RobotFrameworkCamelUtils { List<String> variableKeyValuePairList = new ArrayList<>(); for (Map.Entry<String, Object> variableEntry : variablesMap.entrySet()) { if (ROBOT_VAR_CAMEL_BODY.equals(variableEntry.getKey())) { + if (variableEntry.getValue() == null) { + // no body (such as the consumer), so there is no body variable to pass + continue; + } String bodyVariable = variableEntry.getKey() + ROBOT_VAR_FIELD_SEPERATOR + exchange.getContext().getTypeConverter().mandatoryConvertTo(String.class, variableEntry.getValue()); @@ -56,45 +60,37 @@ public final class RobotFrameworkCamelUtils { } else if (ROBOT_VAR_CAMEL_HEADERS.equals(variableEntry.getKey())) { // here the param is the headers map createStringValueOfVariablesFromMap(variableKeyValuePairList, - ObjectHelper.cast(Map.class, variableEntry.getValue()), exchange, new StringBuilder(), - ROBOT_VAR_CAMEL_HEADERS, true); + ObjectHelper.cast(Map.class, variableEntry.getValue()), exchange, ROBOT_VAR_CAMEL_HEADERS); } else if (ROBOT_VAR_CAMEL_VARIABLES.equals(variableEntry.getKey())) { - // here the param is the headers map + // here the param is the variables map createStringValueOfVariablesFromMap(variableKeyValuePairList, exchange.getVariables(), - exchange, new StringBuilder(), ROBOT_VAR_CAMEL_VARIABLES, true); + exchange, ROBOT_VAR_CAMEL_VARIABLES); } else if (ROBOT_CAMEL_EXCHANGE_NAME.equals(variableEntry.getKey())) { // here the param is camel exchange createStringValueOfVariablesFromMap(variableKeyValuePairList, exchange.getProperties(), - ObjectHelper.cast(Exchange.class, variableEntry.getValue()), - new StringBuilder(), ROBOT_VAR_CAMEL_PROPERTIES, true); + ObjectHelper.cast(Exchange.class, variableEntry.getValue()), ROBOT_VAR_CAMEL_PROPERTIES); } } return variableKeyValuePairList; } + /** + * Adds a robot variable (name:value) for each entry of the map, where the name is the given prefix and the key. A + * nested map adds its entries with the key appended to the prefix. A null value is skipped, as a robot variable + * cannot be null; the test can then fall back to a default value from its own variable table. + */ @SuppressWarnings("unchecked") private static void createStringValueOfVariablesFromMap( - List<String> list, Map<String, Object> headersMap, Exchange exchange, StringBuilder headerVariableName, - String baseName, - boolean includeBaseName) + List<String> list, Map<String, Object> map, Exchange exchange, String prefix) throws TypeConversionException, NoTypeConversionAvailableException { - for (Map.Entry<String, Object> entry : headersMap.entrySet()) { - if (includeBaseName) { - headerVariableName.append(baseName); - } - headerVariableName.append(ROBOT_VAR_NESTING_SEPERATOR).append(entry.getKey()); - if (entry.getValue() instanceof Map) { - createStringValueOfVariablesFromMap(list, ObjectHelper.cast(Map.class, entry.getValue()), exchange, - headerVariableName, headerVariableName.toString(), false); - } else { - headerVariableName.append(ROBOT_VAR_FIELD_SEPERATOR) - .append(exchange.getContext().getTypeConverter().mandatoryConvertTo(String.class, entry.getValue())); - } - list.add(headerVariableName.toString()); - if (includeBaseName) { - headerVariableName = new StringBuilder(); - } else { - headerVariableName = new StringBuilder(baseName); + for (Map.Entry<String, Object> entry : map.entrySet()) { + String name = prefix + ROBOT_VAR_NESTING_SEPERATOR + entry.getKey(); + Object value = entry.getValue(); + if (value instanceof Map) { + createStringValueOfVariablesFromMap(list, ObjectHelper.cast(Map.class, value), exchange, name); + } else if (value != null) { + list.add(name + ROBOT_VAR_FIELD_SEPERATOR + + exchange.getContext().getTypeConverter().mandatoryConvertTo(String.class, value)); } } } diff --git a/components/camel-robotframework/src/main/java/org/apache/camel/component/robotframework/RobotFrameworkEndpoint.java b/components/camel-robotframework/src/main/java/org/apache/camel/component/robotframework/RobotFrameworkEndpoint.java index 51dbd1886611..1012c23c90cc 100644 --- a/components/camel-robotframework/src/main/java/org/apache/camel/component/robotframework/RobotFrameworkEndpoint.java +++ b/components/camel-robotframework/src/main/java/org/apache/camel/component/robotframework/RobotFrameworkEndpoint.java @@ -45,7 +45,7 @@ import org.robotframework.RobotFramework; producerIn = @BodyType(value = Carrier.ANY, description = "The test gets the body converted to a String as the body variable, and the" + " headers and exchange properties as headers.name and properties.name; a" - + " null body or header value fails the exchange"), + + " null body, header or property is not passed"), producerOut = @BodyType(value = Carrier.UNCHANGED, description = "The body is left as it is. The CamelRobotReturnCode header has the return" + " code of the run (0 when all tests pass, non-zero" diff --git a/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkCamelUtilsTest.java b/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkCamelUtilsTest.java index f912813e9a5d..ec9514ed0fa8 100644 --- a/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkCamelUtilsTest.java +++ b/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkCamelUtilsTest.java @@ -18,6 +18,7 @@ package org.apache.camel.component.robotframework; import java.math.BigDecimal; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -29,6 +30,7 @@ import org.apache.camel.util.ObjectHelper; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class RobotFrameworkCamelUtilsTest extends CamelTestSupport { @@ -129,6 +131,50 @@ public class RobotFrameworkCamelUtilsTest extends CamelTestSupport { exchange.getIn().getHeader(RobotFrameworkCamelConstants.CAMEL_ROBOT_RETURN_CODE))); } + @Test + public void testNullBodyIsSkipped() throws Exception { + Exchange nullBody = createExchangeWithBody(null); + nullBody.getIn().setHeader("stringKey", "str1"); + + List<String> variables = RobotFrameworkCamelUtils.createRobotVariablesFromCamelExchange(nullBody, false); + + assertEquals(List.of("headers.stringKey:str1"), variables); + } + + @Test + public void testNullHeaderPropertyAndVariableAreSkipped() throws Exception { + exchange.getIn().setHeader("stringKey", "str1"); + exchange.getIn().setHeader("nullKey", null); + exchange.setProperty("stringKey", "str2"); + exchange.setProperty("nullKey", null); + exchange.setVariable("stringKey", "str3"); + exchange.setVariable("nullKey", null); + Map<String, Object> inner = new HashMap<>(); + inner.put("innerNullKey", null); + exchange.getIn().setHeader("inner", inner); + + List<String> variables = RobotFrameworkCamelUtils.createRobotVariablesFromCamelExchange(exchange, true); + + assertEquals(4, variables.size(), "Unexpected variables: " + variables); + assertTrue(variables.containsAll(List.of("body:Hello Robot", "headers.stringKey:str1", "properties.stringKey:str2", + "variables.stringKey:str3")), "Unexpected variables: " + variables); + } + + @Test + public void testNestedMapEntriesAreAddedOnce() throws Exception { + Map<String, Object> inner = new LinkedHashMap<>(); + inner.put("first", "a"); + inner.put("second", "b"); + exchange.getIn().setHeader("inner", inner); + exchange.getIn().setHeader("empty", new HashMap<>()); + + List<String> variables = RobotFrameworkCamelUtils.createRobotVariablesFromCamelExchange(exchange, false); + + assertEquals(3, variables.size(), "Unexpected variables: " + variables); + assertTrue(variables.containsAll(List.of("body:Hello Robot", "headers.inner.first:a", "headers.inner.second:b")), + "Unexpected variables: " + variables); + } + @Override protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { diff --git a/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkComponentTest.java b/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkComponentTest.java index 249cd05902e1..6db2a5e1d6e0 100644 --- a/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkComponentTest.java +++ b/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkComponentTest.java @@ -109,6 +109,26 @@ public class RobotFrameworkComponentTest extends CamelTestSupport { exchange.getIn().getHeader(RobotFrameworkCamelConstants.CAMEL_ROBOT_RETURN_CODE))); } + @Test + public void testRobotFrameworkCamelNullBodyHeaderAndProperty() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:resultNoBody"); + mock.expectedMessageCount(1); + + template.send("direct:setVariableCamelNoBody", exchange -> { + exchange.getIn().setBody(null); + exchange.getIn().setHeader("stringKey", "headerValue"); + exchange.getIn().setHeader("nullKey", null); + exchange.setProperty("stringKey", "propertyValue"); + exchange.setProperty("nullKey", null); + }); + + MockEndpoint.assertIsSatisfied(context); + + Exchange exchange = mock.getExchanges().get(0); + assertEquals(0, (int) ObjectHelper.cast(Integer.class, + exchange.getIn().getHeader(RobotFrameworkCamelConstants.CAMEL_ROBOT_RETURN_CODE))); + } + @Override protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { @@ -136,6 +156,10 @@ public class RobotFrameworkComponentTest extends CamelTestSupport { "robotframework:src/test/resources/org/apache/camel/component/robotframework/set_variable_camel_property.robot?xunitFile=target/out.xml&allowContextMapAll=true") .to("mock:resultProperty"); + from("direct:setVariableCamelNoBody").to( + "robotframework:src/test/resources/org/apache/camel/component/robotframework/set_variable_camel_no_body.robot?xunitFile=target/out.xml&allowContextMapAll=true") + .to("mock:resultNoBody"); + from("direct:setVariableCamelBodyResourceUri") .setHeader(RobotFrameworkCamelConstants.CAMEL_ROBOT_RESOURCE_URI) .constant("src/test/resources/org/apache/camel/component/robotframework/set_variable_camel_body.robot") diff --git a/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkConsumerTest.java b/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkConsumerTest.java new file mode 100644 index 000000000000..10f6cce78968 --- /dev/null +++ b/components/camel-robotframework/src/test/java/org/apache/camel/component/robotframework/RobotFrameworkConsumerTest.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.robotframework; + +import org.apache.camel.Exchange; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class RobotFrameworkConsumerTest extends CamelTestSupport { + + @Test + public void testConsumerRunsTest() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + + MockEndpoint.assertIsSatisfied(context); + + Exchange exchange = mock.getExchanges().get(0); + assertNull(exchange.getIn().getBody()); + assertEquals(0, exchange.getIn().getHeader(RobotFrameworkCamelConstants.CAMEL_ROBOT_RETURN_CODE, Integer.class)); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + from("robotframework:src/test/resources/org/apache/camel/component/robotframework/send_no_camel_exchnage_only_camel_configs.robot" + + "?xunitFile=target/out-consumer.xml&outputDirectory=target&repeatCount=1") + .to("mock:result"); + } + }; + } +} diff --git a/components/camel-robotframework/src/test/resources/org/apache/camel/component/robotframework/set_variable_camel_no_body.robot b/components/camel-robotframework/src/test/resources/org/apache/camel/component/robotframework/set_variable_camel_no_body.robot new file mode 100644 index 000000000000..7797b1a9b87d --- /dev/null +++ b/components/camel-robotframework/src/test/resources/org/apache/camel/component/robotframework/set_variable_camel_no_body.robot @@ -0,0 +1,27 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +*** Variables *** +${body} no body + +*** Test Cases *** +Set Variable Camel No Body Test Case + Should Be Equal ${body} no body + Should Be Equal ${headers.stringKey} headerValue + Should Be Equal ${properties.stringKey} propertyValue + Variable Should Not Exist ${headers.nullKey} + Variable Should Not Exist ${properties.nullKey}
