Approach to unit testing interaction with a base c

2019-04-11 06:38发布

问题:

There seems to be three general patterns for testing the way a derived class interacts with it's base1. I don't really like any of them, for the reasons I've listed below. Has anyone had long term success with one of these (or another) methods for testing base class interaction?

  • Change the access modifiers to allow Friend (internal in C#) access and set InternalsVisibleTo to include the mocking framework / unit test assembly

Changing the SUT to allow for testing is a test smell. If the method is Protected, it's Protected because that's the appropriate design for it (I actually have yet to see what I would call a "valid" use of Protected Friend (protected internal)).

  • Use reflection and an extension method to create an accessible version of the method you want to mock... then mock it

This requires a lot of extra work to mock a single method, it's not completely type-safe (e.g. a rename would kill it), and (at least in VB), requires creating a Module to put the method in to, which is a design nightmare (modules cannot go inside classes, so they need to be Friend at the most restricted, and you generics are more complicated)!

  • Use state testing instead of behavior testing.

Depending on how complex the base class is, this can require a lot more tests than a single behavior test for the same thing. Consider what would be required in state testing to match a Me.AssertWasCalled(Function(s) s.SendMessage(messageText, [to])) where SendMessage is a base class Protected method.

1NOTE: This is not necessary in Moq which supports mocking protected methods via String names of the method. As Ayende mentions in the link above, he specifically avoided any non compile-time type safe mocking in Rhino Mocks (which I think is a good thing!)

回答1:

Just my humble opinion.

Generaly it is not a good idea to test interactions with base class. As you are going to test implementation details here.

If testing inherited class togehter with base class seems to be complicated then it is probably time to refactor and use aggregation instead of inheritance?