Как воспроизводимо вызвать / спровоцировать ReflectionTypeLoadException?
К сожалению, ссылки на это исключение обычно имеют экзотическую природу и могут произойти, когда вы, например, перечислите Типы через Assembly.GetTypes()
- в данном случае это происходит в одном из наших развертываний, но тот же набор сборок прекрасно работает на Integration Server.
Чтобы защититься от ошибок такого типа, я хотел бы иметь возможность спровоцировать такое исключение, чтобы увидеть, работает ли мой код обработки исключений так, как ожидалось.
Следовательно, любые указатели будут полезны, например, просто зная, какие вещи вызывают это исключение.
РЕДАКТИРОВАТЬ Моя попытка до сих пор:
- Определите тип в сборке A, который использует атрибут сборки B
- Иметь некоторый код для всех типов в сборке, где указан указанный атрибут.
- Я создаю атрибут только тогда, когда флаг DEBUG имеет значение true
- Затем я копирую сборку релиза этой зависимости в соответствующую папку
Но мне удается только получитьTypeLoadException
с довольно четким сообщением об ошибке
2 ответа
Следующее вызывает это исключение:
У вас есть сборка A, которая определяет следующий класс:
public class AC
{
public BC GetBC() { /* ... */ }
}
У вас есть сборка B, которая определяет класс BC
, Теперь, когда вы загружаете сборку А и получаете членов класса 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
точно указав, какой тип он не может загрузить.
Другой подход, если вы хотите проверить, как ваш код обрабатывает исключение, - это использовать в своем тестировании макетирование. С помощью насмешек вы можете смоделировать подсистему загрузки сборок и сконцентрироваться на тестировании того, как вы обрабатываете возникающее исключение - гораздо проще.
Используя насмешку, вы бы использовали 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...
}