Подтвердить что ты не робот

Entity Framework 4.3 и Moq не могут создавать DbContext mock

Следующий тест, который работал с EF 4.2, теперь вызывает следующее исключение с EF 4.3

System.ArgumentException: тип для mock должен быть интерфейсом или абстрактного или непечатаемого класса. ---- > System.TypeLoadException: Метод "CallValidateEntity" в типе "Castle.Proxies.DbContext43Proxy" из сборки 'DynamicProxyGenAssembly2, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null 'отменяет метод, который не видно из этой сборки.

[Test]
public void CanCreateMoqTest()
{
    // Arrange
    Mock<DbContext43> mock;

    // Act
    mock = new Mock<DbContext43>();

    // Assert
    Assert.NotNull(mock.Object);
}

public class DbContext43:DbContext
{
}

Что мне делать? Создать интерфейс для моего DbContext43?

Является ли это изменением между 4.2 и 4.3?

Спасибо!!

4b9b3361

Ответ 1

Спасибо, что нашли это. Проблема вызвана атрибутами InternalsVisibleTo, которые мы удалили из выпуска EF 4.2, но остались в EF 4.3. Это позволило Moq (который мы используем для наших тестов), чтобы увидеть внутренности EntityFramework.dll. Однако, поскольку ваша сборка не может видеть эти внутренние элементы, вы попали в исключение.

Мы планируем сделать выпуск патча EF 4.3 в течение следующих нескольких недель и будем лишать InternalsVisibleTo из этой версии, после чего издевательство должно работать снова.

Обновление: теперь это исправлено в EF 4.3.1 (и EF 5.0-beta1), выпущенном сегодня. Обновите пакет NuGet, чтобы получить исправление. Подробнее см. http://blogs.msdn.com/b/adonet/archive/2012/02/29/ef4-3-1-and-ef5-beta-1-available-on-nuget.aspx.

Ответ 2

Этот вид исключения обычно указывает, что элемент, который вы пытаетесь переопределить, не отображается как часть открытого интерфейса в данной сборке (а может быть, точнее - переопределение сборки не видит его). И если мы посмотрим в CallValidateEntity реализации в EntityFramework 4.3:

internal virtual DbEntityValidationResult CallValidateEntity(
    DbEntityEntry entityEntry, IDictionary<object, object> items)
{
    return this.ValidateEntity(entityEntry, items);
}

Мы действительно замечаем, что этот метод internal, и в результате попадает в категорию без переопределения (используется атрибут non-overridable с учетом атрибута InternalsVisibleTo). Это, естественно, соответствует правильной записи метаданных:

Method #20 (06000a03)
-------------------------------------------------------
  MethodName: CallValidateEntity (06000A03)
  Flags     : [Assem] [Virtual] [HideBySig] [NewSlot]  (000003c3)

Непонятно, почему Moq пытается переопределить этого участника... учитывая, что он не должен видеть его на первом месте.

Обертка вашего контекста в интерфейсе и использование только тех методов, которые вы используете, является жизнеспособным вариантом - этого должно быть достаточно, чтобы пройти тест.