3

I faced a problem asserting two anonymous types.

What I've done so far

  • I have unit test project which sees the internals of my project under test, so anonymous types are visible to test project.
  • I've read about anonymous types behaving more like structures(value types) rather than reference types here: Why anonymous types Equals implementation compares fields?

Yet again, while trying to test again equality following assertion exceptions occur:

1.

Assert.IsTrue(actionResult.Value.Equals(expectedActionResult.Value));

Expected: True But was: False

2.

Assert.AreEqual(actionResult.Value, expectedActionResult.Value);

Expected: <{ errorCode = -4, errorMessage = Invalid or Missing parameters within the request. }> (<>f__AnonymousType0'2[System.Int32,System.String]) But was: <{ errorCode = -4, errorMessage = Invalid or Missing parameters within the request. }> (<>f__AnonymousType0'2[System.Int32,System.String])

This is where I create real and expected result:

var actionResult = _systemUnderTest.GetToken(null) as JsonResult;
var expectedActionResult = 
    new JsonResult(new
    {
        errorCode = (int)ErrorCodes.InvalidOrMissingParameters, errorMessage = ErrorCodes.InvalidOrMissingParameters.GetDescription()
    });

What am I missing?

kuskmen
  • 3,648
  • 4
  • 27
  • 54
  • 1
    You could also take a look at the answer provided here https://stackoverflow.com/questions/38439811/how-do-you-unit-test-asp-net-core-mvc-controllers-that-return-anonymous-objects/38446754#38446754 – Nkosi Aug 07 '17 at 10:28

1 Answers1

2

Even though the anonymous types are accessible in your test project, that doesn't mean they'll be used when you write new { ... }.

If you look at actionResult.Value.GetType() and expectedActionResult.Value.GetType() I strongly suspect you'll see that they're different types from different assemblies.

The simplest workaround in this case is probably just to compare the resulting JSON instead.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • `actionResult.Value.GetType().Module.ScopeName` and `expectedActionResult.Value.GetType().ScopeName` yielded their different assemblies, but apart from that at first glance everything else was the same, even the `UnderlyingSystemType` which is strange doesn't compiler generate these names every time and does that mean that anonymous types can't be tested across assemblies? – kuskmen Aug 07 '17 at 08:44
  • 1
    @kuskmen: If they're in different assemblies, everything else is completely irrelevant - they're different types. The equality comparison in anonymous types first checks that the types are the same, as is common for equality checks. – Jon Skeet Aug 07 '17 at 08:46
  • From what I've saw while debugging generated code by the compiler I noticed that casting from object to that particular compiler generated anonymous type fails therefore Equals method returns false. `[DebuggerHidden] public override bool Equals(object value) { var <>f__AnonymousType = value as <>f__AnonymousType0<j__TPar>; return <>f__AnonymousType != null && EqualityComparer<j__TPar>.Default.Equals(this.i__Field, <>f__AnonymousType.i__Field); }` – kuskmen Aug 07 '17 at 09:11