JustDummies

Just dummies — but seriously powerful ones.

Documentation sections

JD003: AwaitableBodyPassedToReproducibly

PropertyValue
CategoryReproducibility (JustDummies.Reproducibility)
Severity🔴 Error
Enabled by defaultYes

JD001 reports an async lambda passed to Any.Reproducibly. Two neighbouring shapes do the same damage and JD001 does not see either, because it reads the lambda’s own async marker:

  • a synchronous lambda whose body produces a task — Any.Reproducibly(() => sut.SaveAsync(x)). The lambda binds to Action, so the task is created and dropped. CS4014 does not fire, because the enclosing lambda is not itself async;
  • an async void method passed as a method group — Any.Reproducibly(Body). It binds to Action with no warning, and its post-await exception escapes the reproducible scope’s try/catch entirely.

In both cases Any.Reproducibly returns before the body’s assertions run, and their failures never reach the test runner. The test passes green.

Pass the asynchronous body to Any.ReproduciblyAsync(Func<Task>) and await it.

Noncompliant

[Fact]
public void Prices_are_saved() {
    Any.Reproducibly(() => _repository.SaveAsync(price));   // JD003: the task is dropped
}

[Fact]
public void Prices_are_saved_too() {
    Any.Reproducibly(SaveAsync);                            // JD003: 'async void' bound to Action
}

private static async void SaveAsync() { /* ... */ }

Compliant

[Fact]
public async Task Prices_are_saved() {
    await Any.ReproduciblyAsync(() => _repository.SaveAsync(price));
}

What it does not flag

  • A nested lambda or local function inside the body. Its binding and its author’s intent are its own, so a deliberate fire-and-forget there is not this call’s business.
  • An async lambda — that is JD001’s subject, and reporting both would raise two errors for one mistake.
  • A body whose calls all return void.

Read the source, or correct it there opens in a new tab· Mirrored from lib-v1.0.0-preview.6