I have a C# project library DLL with an internal class, and I want to unit test it. I want to specifically unit test this internal class by getting a reference to it using reflection, if possible.
I have this class:
namespace ProjectA.B.C
{
class Caching
{
public static void DoWork() { }
}
}
How can I call the DoWork
method using reflection from another project that uses ProjectA
? I have tried, but my first issue is that typeof(ProjectA.B.C.Caching)
is protected so I can't seem to even get the type reference yet, but I'm sure there is a way.
The error is :
'ProjectA.B.C.Caching' is inaccessible due to its protection level
You can use the InternalsVisibleToAttribute to make the internal class visible to your unit test project.
https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute(v=vs.110).aspx
If the other project has the name ProjectA.B.C
and spits out an assembly named ProjectA.B.C
, and it has the following internal class implementation with the following method signatures and the following namespace:
namespace ProjectA.B.C
{
class Caching
{
public static bool GetOrSet<T>(string key, Func<T> getValue, out T value, TimeSpan? expiration = null) {
...
}
public static bool Get<T>(string key, out T value) {
...
}
}
}
You can call it like this for unit testing:
var type = Assembly.Load("ProjectA.B.C").GetTypes().First(x => x.Name.Equals("Caching", StringComparison.Ordinal));
var methods = type.GetMethods();
var getOrSetMethod = methods.First(x => x.Name.Equals("GetOrSet", StringComparison.Ordinal) && x.ReturnType.Name.Equals("Boolean", StringComparison.Ordinal)).MakeGenericMethod(typeof(bool));
var getMethod = methods.First(x => x.Name.Equals("Get", StringComparison.Ordinal)).MakeGenericMethod(typeof(bool));
var resultToSet = true;
Func<bool> action = () => { return resultToSet; };
if (!(bool)getOrSetMethod.Invoke(null, new object[] { "GetOrSet", action, resultToSet, (TimeSpan?)null }))
throw new Exception("Could not set the GetOrSet key to a boolean value of true.");
var parameters = new object[] { "GetOrSet", resultToSet };
if (!(bool)getMethod.Invoke(null, parameters))
throw new Exception("Could not get back the GetOrSet key.");
if ((bool)parameters[1] != true)
throw new Exception("Got the wrong GetOrSet key back.");
The above shows how you can:
- Create generic function parameters.
- Invoke methods with generics by using
MakeGenericMethod(params Type[] typeArguments)
.
- Invoke methods with
out
parameters and check the returned
parameters array for the result.