akka.net icon indicating copy to clipboard operation
akka.net copied to clipboard

Add deferred startup for Akka.TestKit

Open Arkatufus opened this issue 2 years ago • 8 comments

Changes

Add overridable DeferredStart read only propery. When this is set to true, the actor system would not be instantiated in the constructor, it would be started when the Start method is called.

Arkatufus avatar Mar 22 '23 21:03 Arkatufus

@Arkatufus what's the use case for this?

Aaronontheweb avatar Mar 22 '23 21:03 Aaronontheweb

Use case is when we need to perform some setup before TestKit is started. Say we need to start a database, or prime it to do something

Arkatufus avatar Mar 23 '23 13:03 Arkatufus

Use case is when we need to perform some setup before TestKit is started. Say we need to start a database, or prime it to do something

Any reason why this can't be done in an xUnit test fixture first? That's how we do things like startup databases that we need via Docker.NET et al.

Aaronontheweb avatar Mar 23 '23 13:03 Aaronontheweb

I'm just skeptical that this feature is needed, given that there's been a decade of unit tests written - many of which depend on having a live, running database configured in advance - that have never needed this until now. And I don't really want to support multiple different ways of testkit execution in order to support an edge case.

Aaronontheweb avatar Mar 23 '23 13:03 Aaronontheweb

We could do database cleanup at the end of a test, but if the test break, at best, it will create a false negative at the next test, at worse, it will create a cascading failure because the next unit test probably also need a clean database.

State clean-up is best done at the start of a unit test because it decouples unit tests from the garbage generated by the previous unit test, but we could not do that because the ActorSystem always got started in the constructor.

Another blocker is an async code that needs to be run before the ActorSystem. Calling this in the constructor would be disastrous.

Arkatufus avatar Mar 23 '23 13:03 Arkatufus

public class Test: TestKit, IAsyncLifetime
{
  private readonly MyFixture _fixture;
  protected override DeferredStart => true;

  public Test(ITestOutputHelper output, MyFixture fixture)
    : base(MyConfig, nameof(Test), output)
  {
    _fixture = fixture;
  }

  public async Task Initialize()
  {
    await _fixture.CleanupDatabase(); // It is much cleaner this way
    Start();
  }
}

Arkatufus avatar Mar 23 '23 13:03 Arkatufus

The big problem I've found was with Akka.Persistence.Sql where the journal was started before we could do any database cleanup. The clean-up of deleting all tables collided with the journal accessing the database, creating a racy condition where the journal tried to access a table that does not exist anymore.

Arkatufus avatar Mar 23 '23 13:03 Arkatufus

This feature is available in Akka.Hosting.TestKit, but not in Akka.TestKit

Arkatufus avatar Mar 23 '23 14:03 Arkatufus