Guava.Testing.MockCall (Guava v0.35.1)

Copy Markdown View Source

An in-memory Guava.Call for unit-testing agent callbacks without a server.

Guava.Testing.session/3 drives a whole agent against the live test endpoint; MockCall is the complement for fast, offline, deterministic tests: call a single handler directly and assert on the commands it emits — no network, no LLM, no supervision.

A mock records every command your handler emits, in order, and holds an ETS-backed store for field and variable reads, so Guava.Call actions and reads behave exactly as they do on a live call.

test "assigns the intake task on call start" do
  mock = Guava.Testing.MockCall.new()

  {:noreply, _state} =
    MyAgent.handle_call_started(mock.call, MyAgent.initial_state())

  assert [%Guava.Commands.SetTask{task_id: "intake"}] =
           Guava.Testing.MockCall.commands(mock)
end

Pre-seed collected fields and variables that a handler reads back:

mock = Guava.Testing.MockCall.new(fields: %{"email" => "a@b.com"})
Guava.Testing.MockCall.put_variable(mock, "tier", "gold")

Assert on the exact wire shape with command_maps/1:

Guava.Call.send_dtmf(mock.call, "123")
assert [%{"command_type" => "send-agent-dtmf", "digits" => ["1", "2", "3"]}] =
         Guava.Testing.MockCall.command_maps(mock)

Scope

A mock exercises a handler in isolation. It does not run the call runtime, so runtime orchestration — for example, field validators firing automatically when a task completes — is out of scope; cover that with a live session/3. You can still unit-test a validator directly by calling Guava.Agent.handle_validate/4 yourself.

Command capture is per-process

Commands are captured from the process that calls the handler. If a handler offloads work to a spawned Task, emits from that task are not visible to commands/1 unless you await it first.

Summary

Functions

The Guava.Call handle to pass to your handlers. Equivalent to mock.call.

Returns a specification to start this module under a supervisor.

Discard all recorded commands (e.g. between simulated turns).

Every command emitted so far as wire maps (via Guava.Commands.to_map/1), in order — for asserting on the exact serialized shape.

Every command emitted so far, as structs, in the order emitted.

Build a mock call.

Pre-seed a call variable, readable via Guava.Call.get_variable/3.

Pre-seed a collected field value, readable via Guava.Call.get_field/3.

Stop the recorder process. Optional — it is linked to the test process and stops with it.

Types

t()

@type t() :: %Guava.Testing.MockCall{
  call: Guava.Call.t(),
  pid: pid(),
  table: :ets.tid()
}

Functions

call(mock_call)

@spec call(t()) :: Guava.Call.t()

The Guava.Call handle to pass to your handlers. Equivalent to mock.call.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

clear(mock)

@spec clear(t()) :: t()

Discard all recorded commands (e.g. between simulated turns).

command_maps(mock)

@spec command_maps(t()) :: [map()]

Every command emitted so far as wire maps (via Guava.Commands.to_map/1), in order — for asserting on the exact serialized shape.

commands(mock_call)

@spec commands(t()) :: [struct()]

Every command emitted so far, as structs, in the order emitted.

new(opts \\ [])

@spec new(keyword()) :: t()

Build a mock call.

The recorder process is linked to the calling (test) process, so it — and its ETS store — are cleaned up automatically when the test ends.

Options

  • :id — the call/session id (default: a generated "mock-…" id).
  • :call_info — a Guava.CallInfo (default: a PSTN call). Pass a Guava.CallInfo.WebRTC{} to exercise WebRTC-only guards.
  • :fields — map of field_key => value to pre-seed as collected fields.
  • :variables — map of key => value to pre-seed as call variables.

put_variable(mock, key, value)

@spec put_variable(t(), String.t(), term()) :: t()

Pre-seed a call variable, readable via Guava.Call.get_variable/3.

Emits no command, unlike Guava.Call.set_variable/3.

set_field(mock, key, value)

@spec set_field(t(), String.t(), term()) :: t()

Pre-seed a collected field value, readable via Guava.Call.get_field/3.

Emits no command (unlike a field being collected during a live call).

stop(mock_call)

@spec stop(t()) :: :ok

Stop the recorder process. Optional — it is linked to the test process and stops with it.