TestableSaga AdvanceTime

I do not understanding why TestableSaga AdvanceTime indicates timeout when no timeout should have been raised. Maybe AdvanceTime is not working as I think?

I have a simple Saga, that when started request a timeout after 30 minute.
It also haves a Handler to set up a new timeout in 1 hour.

The problem is the last two line, which both fails (one at a time)

  testableSaga.Handle(new StartSaga { }, context).Wait();

  testableSaga.AdvanceTime(TimeSpan.FromMinutes(10)).Result.ToList().Count.Should().Be(0);
  testableSaga.AdvanceTime(TimeSpan.FromMinutes(20)).Result.ToList().Count.Should().Be(1);

  testableSaga.Handle(new MakeNewTimeoutIn1Hour { }, context);

  testableSaga.AdvanceTime(TimeSpan.FromMinutes(30)).Result.ToList().Count.Should().Be(0); //assert fails with 1
  testableSaga.AdvanceTime(TimeSpan.FromHours(1)).Result.ToList().Count.Should().Be(1); //assert fails with 2

Hey @Stig_Christensen,

I would venture to guess your problem is stemming from breaking the conventions of async/await code. When dealing with async code, you should (almost never) use .Wait() or .Result as they probably aren’t going to work as you expect, so what happens is that your code goes on to the next line before the async code has come to its conclusion, so at the end, where you think you’ve advanced time a total of 2 hours, in reality the CurrentTime property on the testable saga has not done that yet.

I would rewrite this code as the following. (And I’m speaking NUnit here - I think you’re using Shouldly but I can’t replicate that off the top of my head so I apologize for that)

await testableSaga.Handle(new StartSaga { }, context);

var to10m = await testableSaga.AdvanceTime(TimeSpan.FromMinutes(10));
var to30m = await testableSaga.AdvanceTime(TimeSpan.FromMinutes(20));

Assert.That(to10m.Length == 0);
Assert.That(to30m.Length == 1);

await testableSaga.Handle(new MakeNewTimeoutIn1Hour { }, context);

var to1h = await testableSaga.AdvanceTime(TimeSpan.FromMinutes(30));
var to2h = await testableSaga.AdvanceTime(TimeSpan.FromHours(1));

Assert.That(to1h.Length == 0);
Assert.That(to2h.Length == 1);

You are right, I should make my test code async for readability. But with proper Wait and Result the behavior should be the same. I have checked, everything is awaited properly, so the odd behavior still remains.

Wouldn’t it also be kind of odd, if forgetting proper waiting would give to many messages? (expecting 0 but receiving 1)

I found the bug! :slight_smile:

Do not pass a testable context to the handlers in a testable saga

await testableSaga.Handle(new StartSaga { }, context);

Do this instead

await testableSaga.Handle(new StartSaga { });

Easy mistake to make, when should I use the context argument?

Ah, without the surrounding method I missed that you were passing the same context into both handler calls. You only need to provide a context if you need to customize it in some way, and then it needs to be a new context for each call.