Testing

# Testing

Opt-in RSpec and Minitest helpers capture published events without touching PGMQ.

## Set it up

The testing module is never autoloaded — you require it.

The testing helpers are never loaded by Zeitwerk, so they can't leak into production. Require them, activate a mode, and clear the store per test.

```ruby
require "pgbus/testing/rspec"

RSpec.configure do |config|
  config.before { Pgbus::Testing.fake! }
  config.after do
    Pgbus::Testing.disabled!
    Pgbus::Testing.store.clear!
  end
end
```

Minitest is the same shape — require `pgbus/testing/minitest` and include `Pgbus::Testing::MinitestHelpers`, which hooks the lifecycle automatically.

## Testing modes

Three modes control how `Publisher.publish` behaves in tests:

| Mode | Behavior | Use for |
| --- | --- | --- |
| `:fake` | Captures events in memory; no PGMQ, no dispatch. | Most unit/integration tests. |
| `:inline` | Captures AND dispatches to matching handlers. | Testing handler side effects. |
| `:disabled` | Pass-through to the real publisher. | Integration tests with real PGMQ. |

```ruby
Pgbus::Testing.fake!     # global
Pgbus::Testing.inline! do
  OrderService.create!(attrs) # handlers fire synchronously
end                           # previous mode restored after the block
```

## Event-bus assertions

Shared by RSpec and Minitest.

```ruby
assert_pgbus_published(count: 1, routing_key: "orders.created") do
  OrderService.create!(attrs)
end

assert_no_pgbus_published(routing_key: "orders.created") do
  OrderService.preview(attrs)
end

# Capture, then dispatch to handlers — for testing side effects:
perform_published_events { OrderService.create!(attrs) }
```

## The RSpec matcher

`have_published_event` chains payload, header, and count constraints:

```ruby
expect { publish_order(order) }
  .to have_published_event("orders.created")
  .with_payload(hash_including("id" => order.id))
  .with_headers(hash_including("x-tenant" => "acme"))
  .exactly(1)

expect { publish_order(order) }.not_to have_published_event("orders.cancelled")
```

## SSE streams in tests

SSE streams use `rack.hijack`, which spawns background threads that take their own database connections — incompatible with Rails' `use_transactional_fixtures`. pgbus detects the test environment and, under `Pgbus::Testing.fake!`/`.inline!`, auto-enables `streams_test_mode`: the streams endpoint returns a stub response with no hijack and no background threads, so your suite stays green without connection-pool surprises.

> **Note:** You rarely set `streams_test_mode` yourself — activating a testing mode turns it on for you.