1

С тех пор я попытался наследовать EFContextProvider, чтобы я мог предоставить Контекст как виртуальное свойство, позволяющее тестировать, и может вводить мой поставщик контекстов в мой репозиторий. Этот новый образец делает работу МОК, но Модульное тестирование по-прежнему не со следующей ошибкой:Как Mock Breeze.EFContextProvider? ОБНОВЛЕНО

Метод испытания MyProj.Infrastructure.MyItemTests.The_MyRepository_MyItems_Should.Return_A_IQuerable_List_of_MyItem_Instances выбросил исключение: System.NullReferenceException: ссылка на объект не указывает на экземпляр объект

/* ** * ** * ** * ** * UPDATE # 2 * ** * ** */ Добавлен репозиторий так что мой пример кода немного яснее.

/********************** THE NEW PATTERN TO SUPPORT IOC ******************************/ 

public interface IMyDbContextProvider { 

    MyDbContext Context { get; } 
    string Metadata { get; } 
    SaveResult SaveChanges(JObject saveBundle); 

} 

public class MyDbContext : BaseContext<MyDbContext>, IMyDbContext { 

    public virtual DbSet<MyItem> MyItem{ get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
     // Use singular table names 
     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 

     // Disable proxy creation and lazy loading; not wanted in this service context. 
     Configuration.ProxyCreationEnabled = false; 
     Configuration.LazyLoadingEnabled = false; 

     modelBuilder.Configurations.Add(new MyItemMap()); 


    } 
} 


public class MyContextProvider : EFContextProvider <MyDBContext> , IMyContextProvider { 

    public MyContextProvider() { 

    } 
    public virtual MyDbContext Context { 
     get { return base.Context; } 
    } 

    public new string Metadata { 
     get { 
      return base.Metadata(); 
     } 
    } 

    public virtual SaveResult SaveChanges(JObject saveBundle) { 
     return base.SaveChanges(saveBundle); 
    } 

    protected override bool BeforeSaveEntity(EntityInfo entityInfo) { 
     return base.BeforeSaveEntity(entityInfo); 
    } 

} 

    public interface IMyRepository { 

    string Metadata { get; } 
    IQueryable<MyItem> GetMyItems{ get; } 
    SaveResult SaveChanges(JObject saveBundle); 

} 
public class MyRepository : IMyRepository { 

    private readonly IMyContextProvider _myContextProvider; 

    public MyRepository (IMyContextProvider myContextProvider) { 
     _myContextProvider = myContextProvider; 
    } 

    public MyDbContext Context { 
     get { 
      return _myContextProvider.Context; 
     } 
    } 

    public string Metadata { 
     get { 
      return _myContextProvider.Metadata; 
     } 
    } 

    public SaveResult SaveChanges(JObject saveBundle) { 
     return _myContextProvider.SaveChanges(saveBundle); 
    } 

    public IQueryable<MyItem> GetMyItems() { 
     get { 
      return Context.MyItems; 
     } 
    } 


} 

/**********************My UNIT TEST SET UP FUNCTION AND TEST FUNCTION****/ 
     [TestInitialize()] 
     public void SetUp() { 
     _querableMyItemData = GetQueryableMyItemData(); //Returns a list of     MyItems.AsQueryable() 


     _mockMyContextProvider = new Mock<IMyContextProvider>(); 

     _mockMyItemSet = new Mock<DbSet<MyItem>>(); 
     _mockMyItemSet.As<IQueryable<MyItem>>().Setup(m => m.Provider).Returns(_querableMyItemData.Provider); 
     _mockMyItemSet.As<IQueryable<MyItem>>().Setup(m => m.Expression).Returns(_querableMyItemData.Expression); 
     _mockMyItemSet.As<IQueryable<MyItem>>().Setup(m => m.ElementType).Returns(_querableMyItemData.ElementType); 
     _mockMyItemSet.As<IQueryable<MyItem>>().Setup(m => m.GetEnumerator()).Returns(_querableMyItemData.GetEnumerator()); 


     _mockMyContextProvider.Setup(m => m.Context.Units).Returns(_mockUnitSet.Object); 

    } 

    [TestMethod] 
    public void Return_A_IQuerable_List_of_MyItem_Instances() { 
     var expectedType = typeof(IEnumerable<MyItem>); 

     var myRepository = new MyRepository(_mockMyContextProvider.Object); 

     var resultingMyItems = myRepository.GetMyItems(); 

     Assert.IsInstanceOfType(resultingMyItems, expectedType); 
    } 

ответ

0

Не глядя глубоко, я замечаю несколько вещей.

Во-первых, вы не сказали нам, что забросило NullReferenceException. «Ссылка на объект, не установленная на экземпляр объекта», не является полезным сообщением, поэтому мы не можем вам помочь.

Во-вторых, вы пытаетесь в MyDbContextProvider виртуализировать членов, которые не являются виртуальными в базе EFContextProvider класса. Вы можете сделать так, что эти члены должны быть виртуальными (и я буду стоять плечом к плечу с вами ... пожалуйста, создайте для этого UserVoice).

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

В-третьих, вы работаете слишком трудно, если установка тест должен дразнить из членов IQueryable класса (например, Provider, Expression, ElementType). Это слишком много трения для эффективного тестирования. Вам нужен другой способ, чтобы сделать ваш хранилище поддающимся проверке.

В-четвертых, поскольку вы не показывали репозиторий (и не беспокоитесь ... уже слишком много кода), я не могу сказать, как myRepository.myItems относится к тестовому макету.

У вас есть действительно хороший момент о том, что EFContextProvider слишком сложно подделать. Это неправильно написано для проверки. Чтобы быть справедливым с его автором, команда EF не очень помогла, так как DbContextObjectContext не выглядит просто виртуализированным.

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

+0

Привет Уорд, очень ценю ответ. – GregL

+0

Добавлен образец репозитория только для того, чтобы мой примерный код был более полным. В любом случае, я заметил, что метод тестовой установки не имеет атрибута TestInitialize. Тест проходит сейчас. Причиной теста является то, что я получаю ожидаемый тип обратно из контекста, когда вызывается метод репозитория GetMyItems.Это немного перебор, чтобы протестировать такой простой метод, это скорее доказательство концепции, так что я знаю, что могу фактически протестировать поставщика контента Breeze. – GregL

+0

Оказывается, нужно только высмеять GetEnumerator, чтобы высмеять ваш Eb6 DbSet. Я обеспокоен тем, что свойства EFContextProvider являются виртуальными, я уверен, что это придет вовремя, надеюсь, я смогу помочь в его продвижении :) Опять Уорд, я очень ценю вклад! – GregL

Смежные вопросы