Documentation
¶
Overview ¶
Package hoppertest has helpers for testing code that uses hopper.
job := hoppertest.RequireInserted[SendEmail](ctx, t, client, nil)
if job.Args.UserID != 42 { ... }
hoppertest.RequireNotInserted[SendEmail](ctx, t, client, nil)
// Run a job's worker directly, without a database round trip.
err := hoppertest.Work(ctx, t, workers, SendEmail{UserID: 42}, nil)
// Start a client for the test; it is stopped when the test ends.
hoppertest.Start(ctx, t, client)
The Require helpers look at live jobs (not yet finalized) of one kind, so they work whether or not a client is started. The Tx variants look inside a transaction, for code that inserts with InsertTx and tests that roll back.
Index ¶
- func RequireInserted[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], ...) *hopper.Job[T]
- func RequireInsertedTx[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], tx TTx, ...) *hopper.Job[T]
- func RequireManyInserted[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], n int, ...) []*hopper.Job[T]
- func RequireManyInsertedTx[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], tx TTx, n int, ...) []*hopper.Job[T]
- func RequireNotInserted[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], ...)
- func RequireNotInsertedTx[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], tx TTx, ...)
- func Start[TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx])
- func Work[T hopper.JobArgs](ctx context.Context, tb testing.TB, workers *hopper.Workers, args T, ...) error
- type RequireOpts
- type WorkOpts
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RequireInserted ¶
func RequireInserted[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], opts *RequireOpts) *hopper.Job[T]
RequireInserted fails the test unless exactly one live job of kind T matching opts exists, and returns it with decoded args. Use RequireManyInserted when several are expected.
func RequireInsertedTx ¶
func RequireInsertedTx[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], tx TTx, opts *RequireOpts) *hopper.Job[T]
RequireInsertedTx is RequireInserted inside the caller's transaction.
func RequireManyInserted ¶
func RequireManyInserted[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], n int, opts *RequireOpts) []*hopper.Job[T]
RequireManyInserted fails the test unless exactly n live jobs of kind T matching opts exist, and returns them in insertion order.
func RequireManyInsertedTx ¶
func RequireManyInsertedTx[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], tx TTx, n int, opts *RequireOpts) []*hopper.Job[T]
RequireManyInsertedTx is RequireManyInserted inside the caller's transaction.
func RequireNotInserted ¶
func RequireNotInserted[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], opts *RequireOpts)
RequireNotInserted fails the test if any live job of kind T matching opts exists.
func RequireNotInsertedTx ¶
func RequireNotInsertedTx[T hopper.JobArgs, TTx any](ctx context.Context, tb testing.TB, client *hopper.Client[TTx], tx TTx, opts *RequireOpts)
RequireNotInsertedTx is RequireNotInserted inside the caller's transaction.
func Start ¶ added in v0.2.0
Start starts client and stops it when the test ends, with a context that outlives ctx so running jobs get their stop grace.
func Work ¶
func Work[T hopper.JobArgs](ctx context.Context, tb testing.TB, workers *hopper.Workers, args T, opts *WorkOpts) error
Work runs the worker registered for T inline, as the client would, with a synthetic job row. Nothing touches the database: the job is not inserted, claimed or finalized, and middleware does not run. The worker's Timeout applies. It returns the worker's error, so callers can check for hopper.Snooze and hopper.Cancel results with errors.As. A worker that uses hopper.ClientFromContext gets a client only if ctx carries one, from hopper.ContextWithClient. hopper.SetOutput and hopper.CompleteTx return hopper.ErrNotInJob, since there is no stored job, while hopper.RecordStep and hopper.RecordCursor keep progress in memory, so that hopper.RunSteps runs every step. hopper.Logger returns slog.Default().
Types ¶
type RequireOpts ¶
type RequireOpts struct {
Queue string
Priority hopper.Priority
MaxAttempts int
State hopper.JobState
// Tags matches jobs that have every one of them.
Tags []string
}
RequireOpts narrows which jobs a Require helper considers. Zero fields match everything.
func (*RequireOpts) String ¶
func (o *RequireOpts) String() string
type WorkOpts ¶
type WorkOpts struct {
Queue string
Attempt int // defaults to 1
Priority hopper.Priority
Metadata json.RawMessage
// Tags are the job's tags, checked and with repeats dropped as an
// insert does: a tag an insert would reject fails the test.
Tags []string
// Progress is the job's progress from an earlier attempt, to test
// resuming. Work runs the job with a copy, which RecordStep and
// RecordCursor update in memory; Progress itself is left as it is.
Progress *hopper.Progress
// Dependencies are the finished dependencies of a workflow step, as a
// claim gives them to a step with StepOpts.Dependencies set. Work runs
// the job with a copy.
Dependencies []hopper.Dependency
}
WorkOpts customizes a job run by Work.