如何模拟通过反射找到的 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
已定义(但这不是一个好的建议)。
我有一个使用反射找到 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
已定义(但这不是一个好的建议)。