Testing Internals in C#

What's a developer to do?

I've seen this come up on Twitter a couple times, and just hit it myself, so I'll jot some things down while I'm thinking of it.

Say I have the following:

public interface IAgent { void Send(IThingy i); ... } public class SpecialAgent : IAgent { private readonly IList<IThingy> queue = new List<Ithingy>(); public void Send(IThingy i) => queue.Add(i); ... }

I want to be able to write a test that confirms that the IThingy was added to the queue when Send() is called. How should I do it?

There are a few ways I can think of off the top of my head:

  1. Make queue public
  2. Make queue internal and add [assembly: InternalsVisibleTo("MyTestAssemblyName")] to the assembly
  3. Move SpecialAgent into an Internal or Impl namespace/assembly

There are advantages and disadvantages to each:

Simply making queue public is obviously the easiest, and since it's not part of the interface, (assuming all usages specify IAgents) clients won't be able to use it without explicitly creating a (or casting to) SpecialAgent, but it's still exposing something that shouldn't necessarily be exposed.

Adding the InternalsVisibleTo() attribute to the assembly with the test assembly name means that the tests can access it, but something feels backwards about the directionality, kind of like C++'s friend declaration, some sort of weird circular half-dependency. The class (and assembly) should be oblivious to its tests.

Lastly, having an Internal or Impl namespace/assembly would further obfuscate the publicness of queue from the interface and intended use, but security through obscurity is hardly security at all.

There are places in the .NET Core and ASP.NET Core codebases where InternalsVisibleTo() is used for exactly this purpose. There are also places where an Internal or Impl namespace is used.

So, what's a developer to do? I think I know which way I'm leaning, but what would you do in my case? Sound off on Twitter using the link below!