1

I'm unit testing an ASP.Net Core API by asserting that my repo layer returns a DTO object. As I'm testing behavior, I don't exactly care what values my DTO object has, so I'm autogenerating them using AutoFixture. I'm also trying to satisfy my company's code smell check, which requires our PRs to have a near 100% test coverage. When I mock my ORM to return my DTO object when called and in turn the function under test returns that object, I end up with my actual being the same object as my expected. When asserting with fluent assertion, it sees the object reference are equal and passes my test. However for test coverage, I will not see a coverage over the DTO's properties' getters. If the object reference where different, fluent assertion calls the getters. How do I force fluent assertion to always check the value of all properties by calling all the getters?

I've tried using ComparingByValue<T> and ComparingByMember<T>. I've also tried IncludingProperties(), IncludingMembers(), IncludingAllDeclaredProperties(), and IncludingAllRuntimeProperties().

        [Fact]
        public void GivenObjectReferenceIsTheSame_FluentAssertionDoesntCallTheGetters()
        {
            var someDTO = _fixture.Create<SomeDTO>();
            var otherDTO = someDTO;

            otherDTO.Should().BeEquivalentTo(someDTO);
        }
        [Fact]
        public void GivenObjectReferenceIsDifferent_FluentAssertionCallsTheGetters()
        {
            var someDTO = _fixture.Create<SomeDTO>();
            var otherDTO = JsonConvert.DeserializeObject<SomeDTO>(JsonConvert.SerializeObject(someDTO));

            otherDTO.Should().BeEquivalentTo(someDTO);
        }

I would like a way to always force fluent assertion to call the getters in order to get test coverage over the DTOs without having to explicitly write useless tests over the DTOs

Guarionex
  • 11
  • 3
  • 3
    100% test coverage is a meaningless metric. You could have 100% test coverage, yet still not be testing the *right* things. More to the point, getting to 100% test coverage almost always creates an upside-down ROI, you're spending more time writing tests than the value that those tests actually provide. Your tests should focus on the most important functionality, and should grow organically from there. Tests for the sake of tests serves no one. – Chris Pratt Aug 19 '19 at 19:29
  • I absolutely and 100% (pun intended) agree with you. The problem is that my company's architecture team are not the most well versed .Net developers. They added SonarQube to block PRs that don't have high test coverage. My API is TDDed, but my tests are only covering 85%. Most of my DTOs are just get from repo and spit out to endpoints without ever calling the getters and setters. Typically DTOs will get tested and covered by proxy by testing behaviors. If I could get fluent assertion to call the getters, I will not have to write a test for the getters and setters – Guarionex Aug 19 '19 at 19:39
  • Would looping over the properties using reflection and asserting equality be enough for you? – Nkosi Aug 19 '19 at 19:47
  • 1
    How much coverage do your tests have? ;) If you start writing all this custom code to automatically test things like getters, then you have test code that itself needs to be tested. – Chris Pratt Aug 19 '19 at 19:55
  • @Nkosi If I where to go that route, it would be easier to just assert on each property than writing a reflection function to get each property. I imagine at some low level, this is was fluent assertion does. I would like to force that behavior – Guarionex Aug 19 '19 at 20:06
  • @ChrisPratt Exactly! Interestingly, test coverage reports all tests at 100% coverage. – Guarionex Aug 19 '19 at 20:09
  • DTO objects are used somewhere, so their getters will be tested in tests of their consumers. – Fabio Aug 20 '19 at 00:13
  • @Fabio That's exactly right. In my case, I have a light ORM that sets my DTO, which test coverage can't see. Then those DTO objects are passed through to endpoints to be consumed by another system, so nobody calls the getters. Which is why I'd like to have fluent assertion validate my actual and expected DTO objects in the test for some function's behavior by value and not by reference in order to trigger code coverage. – Guarionex Aug 20 '19 at 13:34

1 Answers1

1

The short answer is that you can't. You've asked FA to assert that the objects are equivalent, and in fact, they are the same. This satisfies what FA tries to do. The only alternative is to to pass in another instance which has its properties set to the values of the expectation. This can even be an anonymous object. ComparingByValue is only useful to force FA to ignore the Equals implementation and compare the individual fields and properties.

Dennis Doomen
  • 8,368
  • 1
  • 32
  • 44