101V
101V

Reputation: 502

Akka.net Testkit does not mark test case failed despite ActorInitializationException exception

Following is the actor, I've defined (trying to get my head around persistent actor!!)

public class Country : ReceivePersistentActor
{
    public override string PersistenceId => GetType().Name + state.Id;

    private CountryState state;

    public Country()
    {
        Command<CreateCountry>(CreateCountry);
    }

    private bool CreateCountry(CreateCountry cmd)
    {
        Persist(new CountryCeated
        {
            Id = cmd.Id,
            Code = cmd.Code,
            Description = cmd.Description,
            Active = cmd.Active
        }, evt =>
        {
            state = new CountryState
            {
                Id = evt.Id,
                Code = evt.Code,
                Description = evt.Description,
                Active = evt.Active
            };
        });

        return true;
    }
}

Following is unit test case that I've defined:

[TestClass]
public class CountrySpec : TestKit
{
    [TestMethod]
    public void CountryActor_Should_Create_A_Country()
    {
        var country = Sys.ActorOf(Props.Create(() => new Country()), "Country");
        country.Tell(new CreateCountry(Guid.NewGuid(), "UK", "United Kingdom", true));
        ExpectNoMsg();
    }
}

When I run the test case, there is an exception that I can see in the output window of the test case

[ERROR][25/08/2016 08:25:07][Thread 0007][akka://test/user/Country] Object reference not set to an instance of an object.
Cause: [akka://test/user/Country#552449332]: Akka.Actor.ActorInitializationException: Exception during creation ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Domain.Country.get_PersistenceId() in Y:\Spikes\StatefulActors\Domain\Country.cs:line 9
   at Akka.Persistence.Eventsourced.StartRecovery(Recovery recovery)
   at Akka.Persistence.Eventsourced.AroundPreStart()
   at Akka.Actor.ActorCell.<>c__DisplayClass154_0.<Create>b__0()
   at Akka.Actor.ActorCell.UseThreadContext(Action action)
   at Akka.Actor.ActorCell.Create(Exception failure)
   --- End of inner exception stack trace ---
   at Akka.Actor.ActorCell.Create(Exception failure)
   at Akka.Actor.ActorCell.SysMsgInvokeAll(EarliestFirstSystemMessageList messages, Int32 currentState)

but the test case is marked as success enter image description here

Is there any way/settings in the TestKit, where it can be set such that for any exception, mark the test case failed?

Upvotes: 0

Views: 263

Answers (1)

Bartosz Sypytkowski
Bartosz Sypytkowski

Reputation: 7542

By default, any exceptions inside actors are encapsulated - that means they don't bubble up, blowing the rest of the system.

Actors come in systems, and can be tested by observing the way they communicate with each other. Usually it comes up to providing inputs and asserting outputs from actor system - in your case test has passed, since you haven't validated any output. From the perspective of your test, this actor could be dead and it wouldn't make a difference.

Validating an outputs (either by assertion inside actor itself or i.e. using a custom test journal) is the best way to work with tests.

If for some reason you still have to catch exceptions inside actors, you could create supervision strategy bound to i.e. TestActor, where all exceptions could be forwarded:

public class TestingStrategy : OneForOneStrategy
{
    protected TestingStrategy(IActorRef probe) : base(exception =>
    {
        probe.Tell(exception);
        return DefaultDecider.Decide(exception);
    }) { }
}

Upvotes: 2

Related Questions