4

In our project, an assembly combines logic for the IoC-Container, the project internals and the communication layer. The current version evolved to have only internal classes in addin assemblies.

My main problem with this approach is, that the entry point is only available over the IoC-Container. It is not possible to use anything else than reflection to initialize the assembly.

Everything behind the IoC-Interface is defined as implementation detail and therefore not intended for usages outside. It is well known that you should not test implementation detail (such as private and internal methods), because they should be tested through the public interface. It is also well known, that your tests should not use the IoC-Container to setup the SUTs, because that would result in too much dependencies. So we are using the InternalsVisibleTo-Attribute to make internals visible to our test assemblies and test the so called implementation details.

I recognized that one problem could be the mixup between different concerns in that assembly, changing this would make this discussion useless, because classes have to be defined public. Ignoring my concerns with this, isn't the need to test a class enough reason to make it public, the usages of InternalsVisibleTo seems unintended, and a little bit "hacky". The approach to test only against the publicly available IoC-Container is too costly and would result in integration style tests.

The pros of using internals are, that the usages are well known and do not have to be implemented like a public method would have to be (documentation, completeness, versioning,...).

Is there a solution, to not test against internals, but keep their advantages over public classes, or do we have to redefine what an implementation detail is.

2
  • Are you a library vendor who provides assemblies for other devs, and your use of "public" strictly defines what should be used by them from your lib?
    – Doc Brown
    Commented Jun 25, 2012 at 15:29
  • No, the code is used internally only.
    – dwonisch
    Commented Jun 25, 2012 at 15:46

1 Answer 1

7

It is well known that you should not test implementation detail (such as private and internal methods), because they should be tested through the public interface. It is also well known, that your tests should not use the IoC-Container to setup the SUTs, because that would result in too much dependencies.

I understand this point of view, but I also understand that, ultimately, it's about Getting Things Done.™ When the ceremony of best practices begins to interfere with your ability to get things done, it's time to step back and re-evaluate your assumptions.

Let me state equivocally that I always unit test my private and internal methods. Why shouldn't I? A unit test gives me confidence that the method behaves as I expect it to. My unit testing framework does this, not by inheriting from my class (which is why some testing frameworks require that your methods be virtual), but by creating a proxy class which reflects over my actual class to execute those methods.

So we are using the InternalsVisibleTo-Attribute to make internals visible to our test assemblies and test the so called implementation details.

That's what you should be doing. If your best practice is telling you that you can't test your internals, then throw out the best practice.

You can, and should, still test your public methods, but keep them in a separate area so that you can identify them specifically (these tests generally map to requirements, so you can use them to prove that requirements are satisfied).

3
  • 1
    +1: answering with my answer before I could.
    – Telastyn
    Commented Jun 25, 2012 at 16:00
  • but wouldn't that lead to test code duplication, testing the internal classes both as SUT and as part of public SUT?
    – dwonisch
    Commented Jun 25, 2012 at 16:04
  • 1
    @woni: Only if your internal methods have exactly the same signature and behavior as your external methods. If all your external methods are doing is making a call to an internal method, you may not need to test the internal methods at all. But if there is added behavior in the external methods, you may benefit from another (internal) test. Use your best judgement. Unit test code is seldom completely DRY. Commented Jun 25, 2012 at 16:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.