RclexTesting.DSL.Services (RclexTesting (Experimental) v0.12.11)

Copy Markdown View Source

Mock ROS services, call services, and assert requests received by mocked services.

mock_service/3 registers a scenario-owned service implementation and records each request. Use call_service/3 for synchronous clients, then assert or refute recorded requests with expect_service_call/2 and refute_service_call/2.

Options

Every function in this module accepts an optional trailing keyword list:

  • :namespace the namespace of the scenario node. Defaults to the namespace given to scenario/3, or "/".
  • :qos a Rclex.QoS profile. If not specified, Rclex.QoS.profile_services_default/0 is used.
  • :introspection enables service event publishing with :metadata or :contents, and :introspection_qos configures the service event publisher. Both default to the Rclex defaults.
  • :timeout how long to wait, in milliseconds. Defaults to 5000.

Any option other than :timeout is forwarded verbatim to the underlying Rclex call, so options not listed here are supported too.

Summary

Functions

Call a service synchronously and return the response.

Assert that the mocked service received at least one new request.

Register a test service implementation on the scenario node.

Assert that no new request arrives on the mocked service within the timeout.

Assert that no request matching predicate arrives within the timeout.

Functions

call_service(service_name, service_type, request, opts \\ [])

@spec call_service(String.t(), module(), struct(), keyword()) :: struct()

Call a service synchronously and return the response.

Starts a service client on the scenario node on first use. Raises on timeout or connection failure.

response = call_service "/safety/check", SafetyCheck, %SafetyCheck.Request{}
response = call_service "/safety/check", SafetyCheck, %SafetyCheck.Request{}, timeout: 3_000

opts

  • :timeout how long to wait, in milliseconds. Defaults to 5000.
  • :namespace the namespace of the scenario node. Defaults to the namespace given to scenario/3, or "/".
  • :qos a Rclex.QoS profile. If not specified, Rclex.QoS.profile_services_default/0 is used. Only applied when the client is started.
  • :introspection enables service event publishing with :metadata or :contents, and :introspection_qos configures the service event publisher. Both default to the Rclex defaults.

expect_service_call(service_name, service_type)

@spec expect_service_call(String.t(), module()) :: struct()

Assert that the mocked service received at least one new request.

Cursor-based: previous requests already matched by earlier assertions are skipped. Returns the matching request struct.

expect_service_call "/safety/check", SafetyCheck

expect_service_call(service_name, service_type, predicate)

@spec expect_service_call(String.t(), module(), (struct() -> boolean()) | keyword()) ::
  struct()

expect_service_call/2 with either a predicate or options.

expect_service_call "/safety/check", SafetyCheck,
  fn req -> req.robot_id == "hilda_1" end

expect_service_call "/safety/check", SafetyCheck, timeout: 10_000

opts

  • :timeout how long to wait, in milliseconds. Defaults to 5000.
  • :namespace the namespace of the scenario node. Defaults to the namespace given to scenario/3, or "/".

expect_service_call(service_name, service_type, predicate, opts)

@spec expect_service_call(String.t(), module(), (struct() -> boolean()), keyword()) ::
  struct()

expect_service_call/3 with both a predicate and options.

expect_service_call "/safety/check", SafetyCheck,
  fn req -> req.robot_id == "hilda_1" end, timeout: 10_000

mock_service(service_name, service_type, handler, opts \\ [])

@spec mock_service(String.t(), module(), (struct() -> struct()), keyword()) :: :ok

Register a test service implementation on the scenario node.

All incoming requests are recorded in the collector and forwarded to handler. Cleanup is automatic when the scenario ends.

mock_service "/safety/check", SafetyCheck,
  fn _req -> %SafetyCheck.Response{allowed: true} end

mock_service "/safety/check", SafetyCheck, handler,
  qos: Rclex.QoS.profile_services_default(), introspection: :contents

opts

  • :namespace the namespace of the scenario node. Defaults to the namespace given to scenario/3, or "/".
  • :qos a Rclex.QoS profile. If not specified, Rclex.QoS.profile_services_default/0 is used.
  • :introspection enables service event publishing with :metadata or :contents, and :introspection_qos configures the service event publisher. Both default to the Rclex defaults.

refute_service_call(service_name, service_type)

@spec refute_service_call(String.t(), module()) :: :ok

Assert that no new request arrives on the mocked service within the timeout.

refute_service_call "/delete_map", DeleteMap
refute_service_call "/delete_map", DeleteMap, timeout: 500

opts

  • :timeout how long to wait, in milliseconds. Defaults to 200.
  • :namespace the namespace of the scenario node. Defaults to the namespace given to scenario/3, or "/".

refute_service_call(service_name, service_type, opts)

@spec refute_service_call(String.t(), module(), (struct() -> boolean()) | keyword()) ::
  :ok

refute_service_call/2 with either a predicate or options.

refute_service_call "/delete_map", DeleteMap, fn req -> req.force == true end
refute_service_call "/delete_map", DeleteMap, timeout: 500

refute_service_call(service_name, service_type, predicate, opts)

@spec refute_service_call(String.t(), module(), (struct() -> boolean()), keyword()) ::
  :ok

Assert that no request matching predicate arrives within the timeout.

refute_service_call "/delete_map", DeleteMap, fn req -> req.force == true end