How can I use reflection to invoke a method on thi

2019-09-04 19:34发布

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

2条回答
姐就是有狂的资本
2楼-- · 2019-09-04 19:58

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

查看更多
你好瞎i
3楼-- · 2019-09-04 19:59

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.
查看更多
登录 后发表回答