Исключение TypeLoadException при попытке подделать IObjectSet с помощью Moq
У меня есть следующий код установки:
MockOf<IObjectSet<Dummy>>().Setup(c => c.AddObject(dummy)).Verifiable();
MockOf<IObjectContextWrapper>().Setup(c => c.GetObjectSet<Dummy>()).Returns(MockOf<IObjectSet<Dummy>>().Object);
где Dummy
- пустое определение класса, а Dummy
- Dummy
. MockOf<T>()
- это функция управления макетами в базовом классе, которая в основном гарантирует, что каждый раз, когда он вызывает тип, он возвращает тот же макет.
Тест, содержащий этот код установки, сбой TypeLoadException
и следующее сообщение:
System.TypeLoadException: введите 'IObjectSet`1Proxy389e220f10aa4d9281d0b9e136edc1d4' из сборки 'DynamicProxyGenAssembly2, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = a621a9e7e5c32e69' пытается реализовать недоступный интерфейс.
в System.Reflection.Emit.TypeBuilder.TermCreateClass(модуль RuntimeModule, Int32 tk, тип ObjectHandleOnStack)
в System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
в System.Reflection.Emit.TypeBuilder.CreateType()
в Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
в Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode(Тип proxyTargetType, Type [] интерфейсы, параметры ProxyGenerationOptions)
в Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(тип interfaceToProxy, Type [] дополнительныеИнтерфейсыToProxy, опции ProxyGenerationOptions, перехватчики IInterceptor [])
в Moq.Mock 1.<InitializeInstance>b__0()
at Moq.Mock
1.InitializeInstance()
в Moq.Mock`1.get_Object()
в OddEnds.Tests.Data.EntityFramework.RepositoryTest.Delete_DeletesObjectFromObjectSet() в RepositoryTest.cs: строка 43
Я импортировал System.Data.Objects
и ссылался как на System.Data.Entity.dll, так и на Microsoft.Data.Entity.CTP.dll как в тестовом проекте, так и в проекте, в котором находится тестируемый класс. Сборка успешно завершена без ошибок, предупреждений или сообщений (кроме нескольких связанных с кодовыми контрактами...)
Как это исправить?
Ответы
Ответ 1
Являются ли какие-либо интерфейсы или классы, которые вы используете во внутренних тестах? Используете ли вы что-то вроде [assembly: InternalsVisibleTo("YourTestAssembly")]
для того, чтобы получить вещи для компиляции?
Если да, то вам также необходимо добавить один для DynamicProxyGenAssembly2 для того, чтобы Moq динамически генерировать прокси для классов.
//goes in the AssemblyInfo.cs where the internal interfaces / classes are defined
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
Вот ссылка на тему
http://sonofpirate.blogspot.com/2009/09/my-first-foray-into-unit-testing-with.html
Я надеюсь, что это поможет
Ответ 2
Я обнаружил, что в моем случае я создал экземпляр класса Dummy, который будет использоваться в моем unit test, который оказался закрытым (поскольку я действительно не хотел делиться тестовым объектом снаружи).
Мой код был в следующих строках:
var mockMonitor = new Mock<ICacheMonitor<int, PrivateObject>>();
где PrivateObject был определением частного класса в моем TestClass.
Исправление в моем случае, следовательно, должно гарантировать, что любой из типов в вашем конструкторе Mock является общедоступным.
public class PrivateObject () {}
(Очевидно, что я бы не назвал свой публичный объект PrivateObject либо...)
Ответ 3
Я споткнулся о другой случай, который я не мог понять поначалу. Я работал над прокси для интерфейса, созданного внутри моего unit test...
public IDoWork
{
void DoWork();
}
Мне потребовалось время, чтобы понять, что проблема связана не с этим интерфейсом, а скорее с тем, что сам unit test не был общедоступным:
class TestSomething // missing public keyword
{
// .. some test which tries to create a mock of the interface
public IDoWork
{
void DoWork();
}
}
Итак, хотя IDoWork говорит, что он общедоступен, это действительно не так, поскольку он заключен в закрытый класс.
Надеюсь, это поможет кому-то.