charlessolar / Aggregates.NET

.NET event sourced domain driven design model via NServiceBus and GetEventStore

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Testing and tests

charlessolar opened this issue · comments

General issue for code cleanup and writing more tests

  • Switch to xUnit
  • Use Autofixture and FakeItEasy
  • Reduce number of frivolous interfaces
  • Provide easy access to certain internals for foreign testing
  • Get OpenCover working

For foreign testing I envision a TestDomainUnitOfWork object which provides access to building repositories and entities, but stubs out message receiving and event saving. Instead providing easy methods to retrieve

  • the repositories used
  • the entities read
  • the entities changed
  • the events raised / applied

If you want to test a message handler such as

public class Handler :
        IHandleMessages<SayHello>
{
    public async Task Handle(SayHello command, IMessageHandlerContext ctx)
    {
        var world = await ctx.For<World>().TryGet("World");
        if (world == null)
            world = await ctx.For<World>().New("World");

        world.SayHello(command.Message);
    }
}

You would be able to write something like

[Fact]
public async Task should_say_hello() 
{
    var fixture = new Fixture().Customize(new AutoFakeIteasyCustomization());
    
    var uow = new TestDomainUnitOfWork();
    var context = new TestableMessageHandlerContext();

    // sets up eventstore to return an event for hydration
    uow.Read<World>("World").HasEvent<SaidHello>(x => x.Message = "Foo" ); 

    var handler = fixture.Create<Handler>();
    
    // calls command handler with specific command
    await handler.Handle(new SayHello {
        Message = "Bar"
    });

    // events raised in entities are retrievable and comparable
    Assert.True(uow.Saved<World>("World").WroteEvent<SaidHello>(x => x.Message = "Bar"));
}

Addressing the testing library part of this issue - I completed a good stab of a real functional testing helper. Example here

[Theory, AutoFakeItEasyData]
        public async Task should_say_hello(
            TestableContext context,
            Handler handler
            )
        {
            context.UoW.Test<Domain.World>().Plan("World").HasEvent<SaidHello>(x =>
            {
                x.Message = "foo";
            });

            await handler.Handle(new SayHello
            {
                Message = "test"
            }, context).ConfigureAwait(false);

            context.UoW.Test<Domain.World>().Check("World").Raised<SaidHello>(x =>
            {
                x.Message = "test";
            });
        }