pub struct MockCollector<F: Fn(&Metadata<'_>) -> bool> { /* private fields */ }
Expand description
A collector which can validate received traces.
For a detailed description and examples see the documentation
for the methods and the collector
module.
Implementations§
Source§impl<F> MockCollector<F>
impl<F> MockCollector<F>
Sourcepub fn named(self, name: impl ToString) -> Self
pub fn named(self, name: impl ToString) -> Self
Overrides the name printed by the mock subscriber’s debugging output.
The debugging output is displayed if the test panics, or if the test is
run with --nocapture
.
By default, the mock collector’s name is the name of the test
(technically, the name of the thread where it was created, which is
the name of the test unless tests are run with --test-threads=1
).
When a test has only one mock collector, this is sufficient. However,
some tests may include multiple collectors, in order to test
interactions between multiple collectors. In that case, it can be
helpful to give each collector a separate name to distinguish where the
debugging output comes from.
§Examples
In the following example, we create 2 collectors, both expecting to receive an event. As we only record a single event, the test will fail:
use tracing_mock::{collector, expect};
let (collector_1, handle_1) = collector::mock()
.named("collector-1")
.event(expect::event())
.run_with_handle();
let (collector_2, handle_2) = collector::mock()
.named("collector-2")
.event(expect::event())
.run_with_handle();
let _guard = tracing::collect::set_default(collector_2);
tracing::collect::with_default(collector_1, || {
tracing::info!("a");
});
handle_1.assert_finished();
handle_2.assert_finished();
In the test output, we see that the collector which didn’t
received the event was the one named collector-2
, which is
correct as the collector named collector-1
was the default
when the event was recorded:
[collector-2] more notifications expected: [
Event(
MockEvent,
),
]', tracing-mock/src/collector.rs:1276:13
Sourcepub fn event(self, event: ExpectedEvent) -> Self
pub fn event(self, event: ExpectedEvent) -> Self
Adds an expectation that an event matching the ExpectedEvent
will be recorded next.
The event
can be a default mock which will match any event
(expect::event()
) or can include additional expectations.
See the ExpectedEvent
documentation for more details.
If an event is recorded that doesn’t match the ExpectedEvent
,
or if something else (such as entering a span) is recorded
first, then the expectation will fail.
§Examples
use tracing_mock::{collector, expect};
let (collector, handle) = collector::mock()
.event(expect::event())
.run_with_handle();
tracing::collect::with_default(collector, || {
tracing::info!("a");
});
handle.assert_finished();
A span is entered before the event, causing the test to fail:
use tracing_mock::{collector, expect};
let (collector, handle) = collector::mock()
.event(expect::event())
.run_with_handle();
tracing::collect::with_default(collector, || {
let span = tracing::info_span!("span");
let _guard = span.enter();
tracing::info!("a");
});
handle.assert_finished();
Sourcepub fn new_span<I>(self, new_span: I) -> Self
pub fn new_span<I>(self, new_span: I) -> Self
Adds an expectation that the creation of a span will be recorded next.
This function accepts Into<NewSpan>
instead of
ExpectedSpan
directly, so it can be used to test
span fields and the span parent. This is because a
collector only receives the span fields and parent when
a span is created, not when it is entered.
The new span doesn’t need to be entered for this expectation to succeed.
If a span is recorded that doesn’t match the ExpectedSpan
,
or if something else (such as an event) is recorded first,
then the expectation will fail.
§Examples
use tracing_mock::{collector, expect};
let span = expect::span()
.at_level(tracing::Level::INFO)
.named("the span we're testing")
.with_fields(expect::field("testing").with_value(&"yes"));
let (collector, handle) = collector::mock()
.new_span(span)
.run_with_handle();
tracing::collect::with_default(collector, || {
_ = tracing::info_span!("the span we're testing", testing = "yes");
});
handle.assert_finished();
An event is recorded before the span is created, causing the test to fail:
use tracing_mock::{collector, expect};
let span = expect::span()
.at_level(tracing::Level::INFO)
.named("the span we're testing")
.with_fields(expect::field("testing").with_value(&"yes"));
let (collector, handle) = collector::mock()
.new_span(span)
.run_with_handle();
tracing::collect::with_default(collector, || {
tracing::info!("an event");
_ = tracing::info_span!("the span we're testing", testing = "yes");
});
handle.assert_finished();
Sourcepub fn enter<S>(self, span: S) -> Selfwhere
S: Into<ExpectedSpan>,
pub fn enter<S>(self, span: S) -> Selfwhere
S: Into<ExpectedSpan>,
Adds an expectation that entering a span matching the
ExpectedSpan
will be recorded next.
This expectation is generally accompanied by a call to
exit
as well. If used together with only
, this
is necessary.
If the span that is entered doesn’t match the ExpectedSpan
,
or if something else (such as an event) is recorded first,
then the expectation will fail.
§Examples
use tracing_mock::{collector, expect};
let span = expect::span()
.at_level(tracing::Level::INFO)
.named("the span we're testing");
let (collector, handle) = collector::mock()
.enter(&span)
.exit(&span)
.only()
.run_with_handle();
tracing::collect::with_default(collector, || {
let span = tracing::info_span!("the span we're testing");
let _entered = span.enter();
});
handle.assert_finished();
An event is recorded before the span is entered, causing the test to fail:
use tracing_mock::{collector, expect};
let span = expect::span()
.at_level(tracing::Level::INFO)
.named("the span we're testing");
let (collector, handle) = collector::mock()
.enter(&span)
.exit(&span)
.only()
.run_with_handle();
tracing::collect::with_default(collector, || {
tracing::info!("an event");
let span = tracing::info_span!("the span we're testing");
let _entered = span.enter();
});
handle.assert_finished();
Sourcepub fn exit<S>(self, span: S) -> Selfwhere
S: Into<ExpectedSpan>,
pub fn exit<S>(self, span: S) -> Selfwhere
S: Into<ExpectedSpan>,
Adds ab expectation that exiting a span matching the
ExpectedSpan
will be recorded next.
As a span may be entered and exited multiple times,
this is different from the span being closed. In
general enter
and exit
should be paired.
If the span that is exited doesn’t match the ExpectedSpan
,
or if something else (such as an event) is recorded first,
then the expectation will fail.
§Examples
use tracing_mock::{collector, expect};
let span = expect::span()
.at_level(tracing::Level::INFO)
.named("the span we're testing");
let (collector, handle) = collector::mock()
.enter(&span)
.exit(&span)
.run_with_handle();
tracing::collect::with_default(collector, || {
let span = tracing::info_span!("the span we're testing");
let _entered = span.enter();
});
handle.assert_finished();
An event is recorded before the span is exited, causing the test to fail:
use tracing_mock::{collector, expect};
let span = expect::span()
.at_level(tracing::Level::INFO)
.named("the span we're testing");
let (collector, handle) = collector::mock()
.enter(&span)
.exit(&span)
.run_with_handle();
tracing::collect::with_default(collector, || {
let span = tracing::info_span!("the span we're testing");
let _entered = span.enter();
tracing::info!("an event");
});
handle.assert_finished();
Sourcepub fn clone_span<S>(self, span: S) -> Selfwhere
S: Into<ExpectedSpan>,
pub fn clone_span<S>(self, span: S) -> Selfwhere
S: Into<ExpectedSpan>,
Adds an expectation that cloning a span matching the
ExpectedSpan
will be recorded next.
The cloned span does need to be entered.
If the span that is cloned doesn’t match the ExpectedSpan
,
or if something else (such as an event) is recorded first,
then the expectation will fail.
§Examples
use tracing_mock::{collector, expect};
let span = expect::span()
.at_level(tracing::Level::INFO)
.named("the span we're testing");
let (collector, handle) = collector::mock()
.clone_span(span)
.run_with_handle();
tracing::collect::with_default(collector, || {
let span = tracing::info_span!("the span we're testing");
_ = span.clone();
});
handle.assert_finished();
An event is recorded before the span is cloned, causing the test to fail:
use tracing_mock::{collector, expect};
let span = expect::span()
.at_level(tracing::Level::INFO)
.named("the span we're testing");
let (collector, handle) = collector::mock()
.clone_span(span)
.run_with_handle();
tracing::collect::with_default(collector, || {
let span = tracing::info_span!("the span we're testing");
tracing::info!("an event");
_ = span.clone();
});
handle.assert_finished();
Sourcepub fn drop_span<S>(self, span: S) -> Selfwhere
S: Into<ExpectedSpan>,
pub fn drop_span<S>(self, span: S) -> Selfwhere
S: Into<ExpectedSpan>,
This method is deprecated.
Adds an expectation that a span matching the ExpectedSpan
getting dropped via the deprecated function
Collect::drop_span
will be recorded next.
Instead Collect::try_close
should be used on the collector
and should be asserted with close_span
(which hasn’t been
implemented yet, but will be done as part of #539).
Sourcepub fn follows_from<S1, S2>(self, consequence: S1, cause: S2) -> Self
pub fn follows_from<S1, S2>(self, consequence: S1, cause: S2) -> Self
Adds an expectation that a follows_from
relationship will be
recorded next. Specifically that a span matching consequence
follows from a span matching cause
.
For further details on what this causal relationship means, see
Span::follows_from
.
If either of the 2 spans don’t match their respective
ExpectedSpan
or if something else (such as an event) is
recorded first, then the expectation will fail.
Note: The 2 spans, consequence
and cause
are matched
by name
only.
§Examples
use tracing_mock::{collector, expect};
let cause = expect::span().named("cause");
let consequence = expect::span().named("consequence");
let (collector, handle) = collector::mock()
.follows_from(consequence, cause)
.run_with_handle();
tracing::collect::with_default(collector, || {
let cause = tracing::info_span!("cause");
let consequence = tracing::info_span!("consequence");
consequence.follows_from(&cause);
});
handle.assert_finished();
The cause
span doesn’t match, it is actually recorded at
Level::WARN
instead of the expected Level::INFO
, causing
this test to fail:
use tracing_mock::{collector, expect};
let cause = expect::span().named("cause");
let consequence = expect::span().named("consequence");
let (collector, handle) = collector::mock()
.follows_from(consequence, cause)
.run_with_handle();
tracing::collect::with_default(collector, || {
let cause = tracing::info_span!("another cause");
let consequence = tracing::info_span!("consequence");
consequence.follows_from(&cause);
});
handle.assert_finished();
Sourcepub fn record<S, I>(self, span: S, fields: I) -> Self
pub fn record<S, I>(self, span: S, fields: I) -> Self
Adds an expectation that fields
are recorded on a span
matching the ExpectedSpan
will be recorded next.
For further information on how to specify the expected
fields, see the documentation on the field
module.
If either the span doesn’t match the ExpectedSpan
, the
fields don’t match the expected fields, or if something else
(such as an event) is recorded first, then the expectation
will fail.
§Examples
use tracing_mock::{collector, expect};
let span = expect::span()
.named("my_span");
let (collector, handle) = collector::mock()
.record(span, expect::field("parting").with_value(&"goodbye world!"))
.run_with_handle();
tracing::collect::with_default(collector, || {
let span = tracing::trace_span!(
"my_span",
greeting = "hello world",
parting = tracing::field::Empty
);
span.record("parting", "goodbye world!");
});
handle.assert_finished();
The value of the recorded field doesn’t match the expectation, causing the test to fail:
use tracing_mock::{collector, expect};
let span = expect::span()
.named("my_span");
let (collector, handle) = collector::mock()
.record(span, expect::field("parting").with_value(&"goodbye world!"))
.run_with_handle();
tracing::collect::with_default(collector, || {
let span = tracing::trace_span!(
"my_span",
greeting = "hello world",
parting = tracing::field::Empty
);
span.record("parting", "goodbye universe!");
});
handle.assert_finished();
Sourcepub fn with_filter<G>(self, filter: G) -> MockCollector<G>
pub fn with_filter<G>(self, filter: G) -> MockCollector<G>
Filter the traces evaluated by the MockCollector
.
The filter will be applied to all traces received before any validation occurs - so its position in the call chain is not important. The filter does not perform any validation itself.
§Examples
use tracing_mock::{collector, expect};
let (collector, handle) = collector::mock()
.with_filter(|meta| meta.level() <= &tracing::Level::WARN)
.event(expect::event())
.only()
.run_with_handle();
tracing::collect::with_default(collector, || {
tracing::info!("a");
tracing::warn!("b");
});
handle.assert_finished();
Sourcepub fn with_max_level_hint(self, hint: impl Into<LevelFilter>) -> Self
pub fn with_max_level_hint(self, hint: impl Into<LevelFilter>) -> Self
Sets the max level that will be provided to the tracing
system.
This method can be used to test the internals of tracing
,
but it is also useful to filter out traces on more verbose
levels if you only want to verify above a certain level.
Note: this value determines a global filter, if
with_max_level_hint
is called on multiple collectors, the
global filter will be the least restrictive of all collectors.
To filter the events evaluated by a specific MockCollector
,
use with_filter
instead.
§Examples
use tracing_mock::{collector, expect};
let (collector, handle) = collector::mock()
.with_max_level_hint(tracing::Level::INFO)
.event(expect::event().at_level(tracing::Level::INFO))
.only()
.run_with_handle();
tracing::collect::with_default(collector, || {
tracing::debug!("a message we don't care about");
tracing::info!("a message we want to validate");
});
handle.assert_finished();
Sourcepub fn only(self) -> Self
pub fn only(self) -> Self
Expects that no further traces are received.
The call to only
should appear immediately before the final
call to run
or run_with_handle
, as any expectations which
are added after only
will not be considered.
§Examples
Consider this simple test. It passes even though we only expect a single event, but receive three:
use tracing_mock::{collector, expect};
let (collector, handle) = collector::mock()
.event(expect::event())
.run_with_handle();
tracing::collect::with_default(collector, || {
tracing::info!("a");
tracing::info!("b");
tracing::info!("c");
});
handle.assert_finished();
After including only
, the test will fail:
use tracing_mock::{collector, expect};
let (collector, handle) = collector::mock()
.event(expect::event())
.only()
.run_with_handle();
tracing::collect::with_default(collector, || {
tracing::info!("a");
tracing::info!("b");
tracing::info!("c");
});
handle.assert_finished();
Sourcepub fn run(self) -> impl Collect
pub fn run(self) -> impl Collect
Consume the receiver and return an impl
Collect
which can
be set as the default collector.
This function is similar to run_with_handle
, but it doesn’t
return a MockHandle
. This is useful if the desired
assertions can be checked externally to the collector.
§Examples
The following test is used within the tracing
codebase:
use tracing_mock::collector;
tracing::collect::with_default(collector::mock().run(), || {
let foo1 = tracing::span!(tracing::Level::TRACE, "foo");
let foo2 = foo1.clone();
// Two handles that point to the same span are equal.
assert_eq!(foo1, foo2);
});
Sourcepub fn run_with_handle(self) -> (impl Collect, MockHandle)
pub fn run_with_handle(self) -> (impl Collect, MockHandle)
Consume the receiver and return an impl
Collect
which can
be set as the default collector and a MockHandle
which can
be used to validate the provided expectations.
§Examples
use tracing_mock::{collector, expect};
// collector and handle are returned from `run_with_handle()`
let (collector, handle) = collector::mock()
.event(expect::event())
.run_with_handle();
tracing::collect::with_default(collector, || {
tracing::info!("a");
});
handle.assert_finished();