I had reason to revisit the automocked base class from a previous blog post. I am working with another code base and have new opportunities for automocking. We have a lot of internal classes. Approximately 30% of the classes are marked as internal. The old approach did not work anymore.
With an internal subject, I got this error:
Inconsistent accessibility: base class 'WithSubject<HelloWorld>' is less accessible than class 'When_GetMessage'
The Dependency Inversion Principle
The D in SOLID stands for the Dependency Inversion Principle:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions.
In other words:
Depend on abstractions, not on concretions.
One way to enforce this between projects in C# is to make classes
The internal access modifier
internal access modifier:
Internal types or members are accessible only within files in the same assembly
This is useful:
A common use of internal access is in component-based development because it enables a group of components to cooperate in a private manner without being exposed to the rest of the application code.
How can the unit tests access the internal classes then?
types that are ordinarily visible only within the current assembly are visible to a specified assembly.
We will add the attribute to the AssemblyInfo file in the project under test, to make the unit test project a friend assembly.
We will use an IoC container to configure the creation of the internal classes. The clients will depend on public interfaces and the IoC container.
At work, we use:
I will mimic the Machine.Fakes
WithFakes base class:
The test fixture will inherit from
The<TFake>()method for creating fakes
My implementation will use:
You can get the example code at https://github.com/hlaueriksson/ConductOfCode
Subject<TSubject>() method gives access the class under test.
This is how the error
Inconsistent accessibility: base class 'WithSubject<HelloWorld>' is less accessible than class 'When_GetMessage' is solved.
The<TFake>() method gives access to the injected dependencies from the subject.
With<TFake>() methods can be used to inject real or fake objects into the subject.
The interfaces are
public, the concrete classes are
The creation of internal classes is configured with StructureMap, the IoC container we are using.
AssemblyInfo.cs is also modified to make the subject accessible for the unit tests:
The client depends on interfaces and uses the IoC container to create concrete classes.
The IoC container scans the assemblies for registries with configuration.
Subject property gives access to the automocked instance via the
Subject<TSubject>() method from the base class.
With<TFake>() methods can be used to inject and setup mocks.
The<TFake>() method is used for setup and verification of mocks.
The unit test sessions