Surajit Ghosh
Surajit Ghosh

Reputation: 1

How to set MQTT connect as property in Jmeter and pass it to other thread to post messages on MQTT broker using Pub sampler

I want to set MQTT connect as a Jmeter property and use this connection in other thread which will post messages concurrently to MQTT broker. What I want to implement is

  1. Set MQTT connect as Jmeter property
  2. 1 thread which will use the connection to post messages to MQTT broker
  3. MQTT disconnect

What I have done so far is using MQTT connect, Publish samplers and MQTT disconnect in same thread group. But when running multiple threads messages are getting failed to publish for other than thread-1.

Please let me know if there is any way to implement this.

Upvotes: 0

Views: 874

Answers (2)

Yaroslav Kharitonov
Yaroslav Kharitonov

Reputation: 1

Below is the solution we came to with Java-developer, who dived into the plugin source code.

Test plan structure:

Test plan

- setUp Thread Group
- - MQTT Connect Sampler
- - JSR223 Sampler Set Props

- Thread Group Pub
- - Once Only Controller
- - - JSR223 Sampler Get Props
- - MQTT Pub Sampler

- tearDown Thread Group
- - JSR223 Sampler Get Props
- - MQTT DisConnect Sampler

JSR223 Sampler Set Props Groovy code:

props.put('mqtt_connection', vars.getObject('conn'));
props.put('mqtt_client_id', vars.getObject('clientId'));

JSR223 Sampler Get Props Groovy code:

vars.putObject('conn', props.get('mqtt_connection'));
vars.putObject('clientId', props.get('mqtt_client_id'));

You can save the following xml content as a jmx-file and open in JMeter:

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan">
      <boolProp name="TestPlan.serialize_threadgroups">true</boolProp>
      <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
    </TestPlan>
    <hashTree>
      <SetupThreadGroup guiclass="SetupThreadGroupGui" testclass="SetupThreadGroup" testname="setUp Thread Group">
        <intProp name="ThreadGroup.num_threads">1</intProp>
        <intProp name="ThreadGroup.ramp_time">1</intProp>
        <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
        <stringProp name="ThreadGroup.on_sample_error">stoptest</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller">
          <stringProp name="LoopController.loops">1</stringProp>
          <boolProp name="LoopController.continue_forever">false</boolProp>
        </elementProp>
      </SetupThreadGroup>
      <hashTree>
        <net.xmeter.samplers.ConnectSampler guiclass="net.xmeter.gui.ConnectSamplerUI" testclass="net.xmeter.samplers.ConnectSampler" testname="MQTT Connect Sampler">
          <stringProp name="mqtt.server">${mqtt_ip}</stringProp>
          <stringProp name="mqtt.port">${mqtt_port}</stringProp>
          <stringProp name="mqtt.version">3.1</stringProp>
          <stringProp name="mqtt.conn_timeout">10</stringProp>
          <stringProp name="mqtt.protocol">TCP</stringProp>
          <stringProp name="mqtt.ws_path"></stringProp>
          <boolProp name="mqtt.dual_ssl_authentication">false</boolProp>
          <stringProp name="mqtt.clientcert_file_path"></stringProp>
          <stringProp name="mqtt.clientcert_password"></stringProp>
          <stringProp name="mqtt.user_name">${mqtt_user}</stringProp>
          <stringProp name="mqtt.password">${mqtt_password}</stringProp>
          <stringProp name="mqtt.client_id_prefix">jmeter_</stringProp>
          <boolProp name="mqtt.client_id_suffix">true</boolProp>
          <stringProp name="mqtt.conn_keep_alive">300</stringProp>
          <stringProp name="mqtt.conn_attampt_max">0</stringProp>
          <stringProp name="mqtt.reconn_attampt_max">0</stringProp>
          <stringProp name="mqtt.conn_clean_session">true</stringProp>
        </net.xmeter.samplers.ConnectSampler>
        <hashTree/>
        <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="JSR223 Sampler Set Props">
          <stringProp name="cacheKey">true</stringProp>
          <stringProp name="filename"></stringProp>
          <stringProp name="parameters"></stringProp>
          <stringProp name="script">props.put(&apos;mqtt_connection&apos;, vars.getObject(&apos;conn&apos;));
props.put(&apos;mqtt_client_id&apos;, vars.getObject(&apos;clientId&apos;));</stringProp>
          <stringProp name="scriptLanguage">groovy</stringProp>
          <stringProp name="TestPlan.comments">Set &quot;global&quot; properties accessible by all threads with broker connection and and client id</stringProp>
        </JSR223Sampler>
        <hashTree/>
      </hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group Pub">
        <stringProp name="TestPlan.comments">Publish events</stringProp>
        <stringProp name="ThreadGroup.num_threads">${threads}</stringProp>
        <intProp name="ThreadGroup.ramp_time">1</intProp>
        <boolProp name="ThreadGroup.same_user_on_next_iteration">false</boolProp>
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller">
          <intProp name="LoopController.loops">-1</intProp>
          <boolProp name="LoopController.continue_forever">false</boolProp>
        </elementProp>
      </ThreadGroup>
      <hashTree>
        <OnceOnlyController guiclass="OnceOnlyControllerGui" testclass="OnceOnlyController" testname="Once Only Controller">
          <stringProp name="TestPlan.comments">Things to do only in the first loop of each thread</stringProp>
        </OnceOnlyController>
        <hashTree>
          <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="JSR223 Sampler Get Props">
            <stringProp name="cacheKey">true</stringProp>
            <stringProp name="filename"></stringProp>
            <stringProp name="parameters"></stringProp>
            <stringProp name="script">vars.putObject(&apos;conn&apos;, props.get(&apos;mqtt_connection&apos;));
vars.putObject(&apos;clientId&apos;, props.get(&apos;mqtt_client_id&apos;));</stringProp>
            <stringProp name="scriptLanguage">groovy</stringProp>
            <stringProp name="TestPlan.comments">Get properties with broker connection and client id</stringProp>
          </JSR223Sampler>
          <hashTree/>
        </hashTree>
        <net.xmeter.samplers.PubSampler guiclass="net.xmeter.gui.PubSamplerUI" testclass="net.xmeter.samplers.PubSampler" testname="MQTT Pub Sampler">
          <stringProp name="mqtt.topic_name">${TOPIC}</stringProp>
          <stringProp name="mqtt.qos_level">1</stringProp>
          <boolProp name="mqtt.add_timestamp">false</boolProp>
          <stringProp name="mqtt.message_type">String</stringProp>
          <stringProp name="mqtt.message_type_fixed_length">1024</stringProp>
          <stringProp name="mqtt.message_to_sent">${MESSAGE}</stringProp>
          <boolProp name="mqtt.retained_message">false</boolProp>
          <stringProp name="TestPlan.comments">Send events</stringProp>
        </net.xmeter.samplers.PubSampler>
        <hashTree/>
      </hashTree>
      <PostThreadGroup guiclass="PostThreadGroupGui" testclass="PostThreadGroup" testname="tearDown Thread Group">
        <intProp name="ThreadGroup.num_threads">1</intProp>
        <intProp name="ThreadGroup.ramp_time">1</intProp>
        <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
        <stringProp name="ThreadGroup.on_sample_error">stoptest</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller">
          <stringProp name="LoopController.loops">1</stringProp>
          <boolProp name="LoopController.continue_forever">false</boolProp>
        </elementProp>
      </PostThreadGroup>
      <hashTree>
        <JSR223Sampler guiclass="TestBeanGUI" testclass="JSR223Sampler" testname="JSR223 Sampler Get Props">
          <stringProp name="cacheKey">true</stringProp>
          <stringProp name="filename"></stringProp>
          <stringProp name="parameters"></stringProp>
          <stringProp name="script">vars.putObject(&apos;conn&apos;, props.get(&apos;mqtt_connection&apos;));
vars.putObject(&apos;clientId&apos;, props.get(&apos;mqtt_client_id&apos;));</stringProp>
          <stringProp name="scriptLanguage">groovy</stringProp>
          <stringProp name="TestPlan.comments">Get properties with broker connection and client id</stringProp>
        </JSR223Sampler>
        <hashTree/>
        <net.xmeter.samplers.DisConnectSampler guiclass="net.xmeter.gui.DisConnectSamplerUI" testclass="net.xmeter.samplers.DisConnectSampler" testname="MQTT DisConnect Sampler">
          <stringProp name="TestPlan.comments">Close mqtt connection</stringProp>
        </net.xmeter.samplers.DisConnectSampler>
        <hashTree/>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

Upvotes: 0

Dmitri T
Dmitri T

Reputation: 168147

I don't think that:

  1. Moving the connection into another Thread Group
  2. Trying to publish messages concurrently with multiple virtual users over a single connection

is a good idea because well-behaved JMeter test must represent real life usage of your application and each JMeter thread (virtual user) must represent an MQTT-enabled device which establishes its own connection to the broker. If the "messages are getting failed to publish" it indicates problem either with your test setup (parameterization, correlation, whatever) or with your MQTT broker so first of all I would check:

See Testing the MQTT Messaging Broker for IoT - A Guide article for more details.


If you're still looking for a way of passing the MQTT connection between thread groups you can do this using JSR223 Test Elements and the following code:

  1. To save the connection into a property:

    props.put('connection', vars.getObject('conn'))
    
  2. To get the connection object from the property:

    vars.putObject('conn', props.get('connection'))
    

Upvotes: 2

Related Questions