0

I'm having a super weird issue when using FakeItEasy in my unit tests...

I'm asserting whether a call has been made to a mock and I specify a constraint on one of the method's parameter, something like:

A.CallTo(() => fakeStorageClient.StoreAsync("commands", A<CommandEnvelope<FakeCommand>>.Ignored, false)).MustHaveHappened(Repeated.Exactly.Once);

The problem is that this assertion fails sometimes. I've noticed that usually it would fail when I run all my tests in one run ("Run All"), but doesn't if I only run this particular Fact alone. As you've noticed, the method is async so I was thinking about some async-related issue, but all the calls are properly awaited.

Looking at the details of the assertion failures, the log is:

Assertion failed for the following call:
Backend.Data.MessageStorage.IMessageStorageClient.StoreAsync("commands", <NULL>, False)
Expected to find it exactly once but found it #0 times among the calls:
1: Backend.Data.MessageStorage.IMessageStorageClient.StoreAsync(
      tableName: "commandStream",
      entity: Backend.Domain.Commands.CommandEnvelope`1[Backend.Domain.Tests.FakeCommand],
      streamMode: True)
2: Backend.Data.MessageStorage.IMessageStorageClient.StoreAsync(
      tableName: "commands",
      entity: Backend.Domain.Commands.CommandEnvelope`1[Backend.Domain.Tests.FakeCommand],
      streamMode: False)

As you see, the expected call did happen (it's the case #2) but for some reason, FakeItEasy was expecting a call with NULL as the second parameter!

I hope someone can help me figure out why FakeItEasy would evaluate the A<CommandEnvelope<FakeCommand>>.Ignored constraint to NULL and moreover, why it would do that only sometimes...

ThomasWeiss
  • 1,292
  • 16
  • 30
  • Do you setup the fake anywhere else? If it fails when you run all, and not when you run alone, it might be an issue of shared state. – Chris Wohlert May 03 '16 at 07:40
  • Nope the fake is created in the same Fact, and actually the assertion succeeds sometimes, even in Run All, but most of the time it doesn't. – ThomasWeiss May 03 '16 at 07:42
  • Even in Run All the order of execution might be different from time to time. I don't know why else this would happen. Is it possible to share the entire test class? – Chris Wohlert May 03 '16 at 07:46
  • Not easy to share the class because of its dependencies, but I'll dig into the fact the tests aren't run in the same order indeed. I guess the best hint is that the traces show that the parameter constraint is evaluated to NULL, I'm wondering if anyone could guess how that could happen. – ThomasWeiss May 03 '16 at 07:53
  • 1
    `A>.Ignored` *always* returns null, but it's evaluated from code that catches the call to `Ignored` and records the constraint. But it should definitely *not* evaluate the constraint as null... Could you please 1) check that it still happens with version 2.0.0-rc2, and 2) open an issue on GitHub? – Thomas Levesque May 03 '16 at 09:27
  • 1
    As @Thomas hints at, this is probably a weakness of the 1.x.y releases. Specifically [issue 476](https://github.com/FakeItEasy/FakeItEasy/issues/476). I expect better results with the 2.0 rc. Or if you run tests in a single thread. – Blair Conrad May 03 '16 at 09:47
  • Hi guys, I just updated to 2.0rc and sure enough, everything works like a charm now. Thanks so much for your support! Should I still file an issue on GH? – ThomasWeiss May 03 '16 at 11:25
  • @ThomasWeiss, it's one of the many thread safety issues in FakeItEasy 1.x that have been fixed in 2.0.0. No need to file an issue. – Thomas Levesque May 03 '16 at 11:47
  • @ThomasLevesque doesn't need the extra rep. Neither do I, but I did add an answer so we can eventually have this question marked as answered. – Blair Conrad May 17 '16 at 19:37
  • Oops, totally forgot to add the answer... thanks @BlairConrad! – Thomas Levesque May 17 '16 at 20:20

1 Answers1

1

The problem turned out to be a manifestation of issue 476, which has been fixed in the latest FakeItEasy 2.0.0 release candidate. Upgrading to that version fixed it, as I expect running tests single-threaded would've.

Blair Conrad
  • 233,004
  • 25
  • 132
  • 111