Reputation: 22849
Sadly, references to this exception are usually of an exotic nature and can happen when you e.g. enumerate Types via Assembly.GetTypes()
- case in point, it is happening on one of our deployments but the same set of assemblies work fine on the Integration Server.
In order to harden against this type of error I would like to be able to provoke such an exception to see if my exception handling code works as expected.
Hence any pointers would be useful, e.g. just knowing what kind of things cause this exception.
EDIT
My attempt so far:
But I only manage to get a TypeLoadException
with a pretty clear error message
Upvotes: 4
Views: 430
Reputation: 38444
Another approach if you wish to test how your code handles the exception is to use mocking in your testing. With mocking you can mock out the assembly loading sub-system and concentrate on testing how you handle the resulting exception - much more straight-forward.
Using mocking you would use an IAssemblyService
instead of calling GetTypes
on Assembly
directly. In your mock you can throw the required exception. It is more usual to use a mocking framework such as FakeItEasy, but the following uses a hand-rolled mock for demonstration.
In your test you would substitute your real assembly service with 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();
}
}
And with a mocking framework such as 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...
}
Upvotes: 2
Reputation: 174329
The following causes this exception:
You have assembly A which defines the following class:
public class AC
{
public BC GetBC() { /* ... */ }
}
You have assembly B which defines the class BC
.
Now, when you load Assembly A and get the members of class AC
, for example using assembly.GetTypes().SelectMany(t => t.GetMembers()).ToList();
, the framework tries to resolve BC
. It even knows that it is in assembly B
. However, if the framework resolves an assembly B
that doesn't contain BC
, a TypeLoadException
will be thrown. This can happen, if assembly B
is not up-to-date, because you forgot it in your deployment.
UPDATE:
To actually get a ReflectionTypeLoadException
, the scenario is very similar. However, you don't need to have a method in AC
that returns BC
but you need to derive AC
from BC
:
public class AC : BC
{
}
Using the LoaderExceptions
property, you can retrieve the exceptions that lead to this ReflectionTypeLoadException
. In my case, this is a TypeLoadException
stating exactly what type it couldn't load.
Upvotes: 4