AshNeo4j.Sandbox (AshNeo4j v0.4.1)

Copy Markdown View Source

Test sandbox for AshNeo4j, analogous to Ecto.Adapters.SQL.Sandbox.

Each test that calls checkout/0 gets a dedicated Neo4j connection with an open transaction. Every Cypher query executed by that test process runs inside that transaction. When the test process exits the transaction is rolled back automatically, so no data persists between tests and safe parallel execution (async: true) is possible.

Usage

Replace the Neo4jHelper.delete_all() pattern with a sandbox checkout:

setup do
  AshNeo4j.Sandbox.checkout()
  on_exit(&AshNeo4j.Sandbox.rollback/0)
end

The on_exit call is optional. ExUnit's on_exit callbacks run in a separate process after the test process has already exited, so by the time rollback/0 is called the transaction has already been rolled back via the holder's exit-signal trap. Including on_exit(&AshNeo4j.Sandbox.rollback/0) is harmless (it becomes a no-op) and is recommended for clarity.

How it works

checkout/0 spawns a holder process linked to the test process. The holder opens a Bolty.transaction/3 and waits for query messages. All Cypher.run/2 calls from the test process are forwarded to the holder and executed on the single sandboxed connection, keeping every write inside the uncommitted transaction.

When the test process exits (pass, fail, or crash) the link delivers an exit signal to the holder. Because the holder traps exits, the signal becomes a message that triggers Bolty.rollback/2, cleanly rolling back the transaction and returning the connection to the pool.

Parallel tests

Because each test's writes are confined to an isolated transaction that is never committed, concurrent tests cannot interfere with each other:

use ExUnit.Case, async: true

setup do
  AshNeo4j.Sandbox.checkout()
  on_exit(&AshNeo4j.Sandbox.rollback/0)
end

Summary

Functions

Checks out a sandbox connection and begins a Neo4j transaction.

Rolls back the sandbox transaction for the current process.

Functions

checkout()

@spec checkout() :: :ok

Checks out a sandbox connection and begins a Neo4j transaction.

All Cypher queries from the calling process are routed to this connection and executed within the open transaction. The transaction is rolled back automatically when the calling process exits.

Raises if called more than once without an intervening rollback/0.

rollback()

@spec rollback() :: :ok

Rolls back the sandbox transaction for the current process.

When called from the same process as checkout/0 this signals the holder to roll back immediately and blocks until the rollback completes.

When called from an on_exit callback (which runs in a different process after the test process has already exited) this is a safe no-op — the transaction has already been rolled back via the holder's exit-signal trap.