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

How to mock a class to be found via reflection?

我有一个使用反射找到 class 的方法,我想对其进行单元测试。

在要测试的程序集中:

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 returns 为空。如果我从测试方法中通过 "RealWork" 它有效。

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

欢迎提出有无第三方框架、工具、插件的建议。

解决方案 根据@LasseV.Karlsen 的评论和@dymanoid 的标记答案,我只是像这样更改了测试方法的代码:

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

您需要使用 AssemblyQualifiedName,因为您的测试类型驻留在不同的程序集中,而不是定义 GetWorkClass 方法的地方。在不提供完整程序集限定名称的情况下,Type.GetType 方法仅在执行程序集和 mscorlib.

中搜索

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