Testing
coretest runs an oryn application in tests, in the test environment:
- all telemetry is exported in memory, whatever the configuration,
- logs are not printed on the console,
- the logger is not set as
slog.Default(), so parallel tests do not interfere.
Start the application
func TestGreet(t *testing.T) { t.Parallel()
var greeter *Greeter
coretest.Start(t, core.New(greet.Module), fx.Populate(&greeter))
assert.Equal(t, "hello oryn", greeter.Greet(t.Context(), "oryn"))}| Function | Description |
|---|---|
coretest.Start(t, app, options...) |
Builds and starts the application, and stops it when the test ends |
coretest.New(t, app, options...) |
Builds the application without starting it |
coretest.TestOptions() |
The options added to every test application, to build an fx.App yourself |
The options come after the application ones: get dependencies with fx.Populate, replace them with fx.Replace or fx.Decorate, and override the configuration with config.AsOptions:
coretest.Start(t, app, config.AsOptions(config.WithValues(map[string]any{"log.level": "debug"})), fx.Decorate(func() Clock { return fakeClock }), fx.Populate(&service),)The application uses the test context as base context: it is cancelled when the test ends.
Assert telemetry
The in-memory exporters are in the container. Assert on them with the otel/oteltest packages:
func TestCheckout(t *testing.T) { t.Parallel()
var ( service *CheckoutService spans *tracetest.InMemoryExporter logs *logtest.InMemoryExporter metrics *sdkmetric.ManualReader )
coretest.Start(t, app, fx.Populate(&service, &spans, &logs, &metrics))
require.NoError(t, service.Checkout(t.Context(), cart))
spantest.HasSpan(t, spans, spantest.WithName("checkout")) logtest.HasRecord(t, logs, logtest.WithBody("checked out"), logtest.WithLevel(slog.LevelInfo)) assert.Equal(t, int64(1), metrictest.Int64Sum(t, metrics, "checkout.orders"))}| Package | Assertions | Filters |
|---|---|---|
spantest |
HasSpan, HasNoSpan, SpanCount, Find |
WithName, WithNameContains, WithKind, WithStatus, WithAttribute, WithAttributeValue, WithParent |
logtest |
HasRecord, HasNoRecord, RecordCount |
WithBody, WithBodyContains, WithLevel, WithSeverity, WithAttribute, WithAttributeValue |
metrictest |
HasMetric, HasNoMetric, Int64Sum, Collect, Find |
WithName, WithUnit, WithAttributeValue |
When an assertion fails, the message lists what was recorded, to see what went wrong without debugging.
Test failures to start
To test that an application fails to start, build it with fx.New and check the error:
app := fx.New(core.New(myModule).Options(coretest.TestOptions(), fx.NopLogger)...)require.ErrorContains(t, app.Err(), "invalid configuration")