可悲的是,对此异常的引用通常具有异国情调,并且可能在您例如通过Assembly.GetTypes()
枚举类型 - 例如,它发生在我们的某个部署上,但同一组程序集在Integration Server上正常工作。
为了加强这种类型的错误,我希望能够引发这样的异常,看看我的异常处理代码是否按预期工作。
因此任何指针都是有用的,例如只知道什么样的事情导致了这个例外。
<击> 修改 到目前为止我的尝试:
但我只设法得到一个 TypeLoadException
,其中包含非常明确的错误消息
答案 0 :(得分:3)
以下原因导致此异常:
您有程序集A,它定义了以下类:
public class AC
{
public BC GetBC() { /* ... */ }
}
您有程序集B,它定义了类BC
。
现在,当您加载程序集A并获取类AC
的成员时,例如使用assembly.GetTypes().SelectMany(t => t.GetMembers()).ToList();
,框架会尝试解析BC
。它甚至知道它在汇编B
中。但是,如果框架解析了不包含B
的程序集BC
,则会抛出TypeLoadException
。如果程序集B
不是最新的,可能会发生这种情况,因为您在部署中忘记了它。
<强>更新强>
要实际获得ReflectionTypeLoadException
,场景非常相似。但是,您不需要AC
中的方法返回BC
,但您需要从AC
派生BC
:
public class AC : BC
{
}
使用LoaderExceptions
属性,您可以检索导致此ReflectionTypeLoadException
的异常。就我而言,这是一个TypeLoadException
,说明它无法加载的类型。
答案 1 :(得分:2)
如果您希望测试代码处理异常的方法,另一种方法是在测试中使用模拟。通过模拟,您可以模拟装配加载子系统,并专注于测试如何处理产生的异常 - 更直接。
使用模拟,您可以使用IAssemblyService
而不是直接在GetTypes
上调用Assembly
。在你的模拟中,你可以抛出所需的异常。使用模拟框架(如FakeItEasy)更常见,但以下使用手动模拟进行演示。
在您的测试中,您将使用MockAssemblyService
替换您的实际装配服务。
internal class MyTypeThatLoadsStuff
{
public MyTypeThatLoadsStuff(IAssemblyService assemblyService)
{
//Do stuff with assemblyService
}
}
internal interface IAssemblyService
{
IEnumerable<Type> GetTypes();
}
internal class AssemblyService : IAssemblyService
{
private readonly Assembly _assembly;
public AssemblyService(Assembly assembly)
{
_assembly = assembly;
}
public IEnumerable<Type> GetTypes()
{
return _assembly.GetTypes();
}
}
internal class MockAssemblyService : IAssemblyService
{
public IEnumerable<Type> GetTypes()
{
throw new ReflectionTypeLoadException();
}
}
使用像FakeItEasy这样的模拟框架:
[Test]
public void Test()
{
IAssemblyService service = A.Fake<IAssemblyService>();
ReflectionTypeLoadException ex = new ReflectionTypeLoadException(
new[] { typeof(SprocketTests) }, new[] { new Exception() });
A.CallTo(() => service.GetTypes()).Throws(ex);
MyTypeThatLoadsStuff loader = new MyTypeThatLoadsStuff(service);
//test...
}