Entity Framework 4.3 и Moq не могут создать макет DbContext - PullRequest
28 голосов
/ 12 февраля 2012

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

System.ArgumentException: тип для mock должен быть интерфейсом или абстрактным или незапечатанным классом.----> System.TypeLoadException: метод 'CallValidateEntity' для типа 'Castle.Proxies.DbContext43Proxy' из сборки 'DynamicProxyGenAssembly2, Version = 0.0.0.0, Culture = нейтральный, 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?

Спасибо !!

Ответы [ 2 ]

38 голосов
/ 13 февраля 2012

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

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

Обновление: теперь это исправлено в 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.

5 голосов
/ 12 февраля 2012

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

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

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

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

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

...