如何模拟通过反射找到的类?

时间:2017-09-19 10:04:13

标签: unit-testing reflection mstest

我有一个使用反射查找类的方法,我想对它进行单元测试。

在待测试的装配中:

namespace MyApp.Workers
{
    internal interface IWork { void DoWork() }

    internal class RealWork : IWork { public void DoWork() { /* impl omitted */ } }
}

namespace MyApp.Helpers
{
    internal static class ClassFetcher
    {
        public static Type GetWorkClass(string className)
        {
            string qualifiedClassName = typeof(IWork).Namespace + "." + className;
            cls = Type.GetType(qualifiedClassName);
            if (cls == null)
                throw new Exception($"Can't find class \"{className}\".");
            if (!typeof(IWork).IsAssignableFrom(cls))
                throw new Exception($"The class \"{className}\" doesn't implement IWork.");
        }
    }
}

在测试装配中:

// Usings omitted...

namespace MyApp.Workers
{
    // Class that does implement IWork.
    public class TestWork : IWork { public void DoWork() {} }

    // Class that does not implement IWork.
    public class TestNoWork { }
}

namespace MyApp_Test.Helpers
{
    [TestClass]
    public class UnitTestClassFetcher
    {
        [TestMethod]
        public void FindsWorkClass()
        {
            ClassFetcher.GetWorkClass("TestWork");
        }

        [TestMethod]
        public void DoesNotAcceptNoWorkClass()
        {
            ClassFetcher.GetWorkClass("TestNoWork");
        }
    }
}

在来自测试程序集的GetWorkClass调用中,Type.GetType(...)内的GetWorkClass调用返回null。如果我从测试方法中传递"RealWork"就可以了。

那么,如何在要测试的程序集中启用Type.GetType(...)调用以查找在单元测试程序集中声明的测试类?

欢迎使用和不使用第三方框架,工具,插件的建议。

根据@ LasseV.Karlsen的评论和@dymanoid的明确答案,我只是更改了测试方法的代码:

[TestMethod]
public void FindsWorkClass()
{
    string namespace = typeof(IWork).Namespace;
    string className = typeof(TestWork).AssemblyQualifiedName.Substring(namespace.Length + 1);
    ClassFetcher.GetWorkClass(className);
}

1 个答案:

答案 0 :(得分:1)

您需要使用AssemblyQualifiedName,因为您的测试类型位于不同的程序集中,而不是GetWorkClass方法定义的位置。如果不提供完整的程序集限定名称,Type.GetType方法仅在执行程序集和mscorlib中搜索。

更改方法的实现,使其使用程序集限定名称(例如,通过提供程序集名称作为可选参数),或者在定义TestWork的同一程序集中定义GetWorkClass类(但这不是一个好建议。)