2014-12-02 4 views
1

Я работаю с .NET 4.5, EF6, и я пытаюсь использовать JustMock 2.0 для тестирования моего применениеJustMock - Как издеваться над методом для всех экземпляров, возвращая результат эквивалентного метода другого класса (общий общий интерфейс

Я пытаюсь дразнить свою базу данных, насмехаясь над моим DbContext подкласса:.. CoreDataRepositoryContext

чтобы сделать это, мне нужно издеваться члену SaveChanges из DbContext и каждый DbSet напечатал свойства моего класса CoreDataRepositoryContext, возвратив поддельный сбор данных. Мне также нужно издеваться следующие членов DbSet «s:

  • Добавить
  • Удалить
  • AsQueryable

мне нужно издеваться над его для всех экземпляров CoreDataRepositoryContext и DbSet

Например, у меня есть en Tities типа Заказать в базе данных (таблица Заказы) я сделал следующее издеваться за столом Заказы:

// FakeOrders is a list of orders (List<Order>) 

var mockedContext = Mock.Create<CoreDataRepositoryContext>(); 

    // Mock works 
Mock.Arrange(() => mockedContext.SaveChanges()).IgnoreInstance().DoNothing(); 
    // Mock works 
Mock.Arrange(() => mockedContext.Orders).IgnoreInstance().ReturnsCollection(FakeOrders); 
    // Mock works 
Mock.Arrange(() => mockedContext.Orders.Add(Arg.IsAny<Order>())).IgnoreInstance().DoInstead((Order o) => FakeOrders.Add(o)); 
    // Mock works 
Mock.Arrange(() => mockedContext.Orders.Remove(Arg.IsAny<Order>())).IgnoreInstance().DoInstead((Order o) => FakeOrders.Remove(o)); 
    // Mock DOES NOT work ! 
Mock.Arrange(() => mockedContext.Orders.AsQueryable()).IgnoreInstance().Returns(() => FakeOrders.AsQueryable()); 

mockedContext.Orders имеет тип DbSet < Order> и FakeOrders имеет тип Список < Заказ>. Оба класса реализуют интерфейс IEnumerable < Заказ>.

Дразнящий Добавить и Удалить пользователей работают хорошо, потому что ни один из двух методов объявлен в интерфейсе IEnumerable < T>.

С другой стороны, AsQueryable объявляется в этом интерфейсе и определяется Queryable. Итак, как я дразнить член, используя IgnoreInstance, вызывая AsQueryable из экземпляра любого класса, который реализует IEnumerable < T> запускает бесконечный цикл. Поскольку IEnumerable < Order> .AsQueryable издевались над FakeOrders.AsQueryable который осмеян ... FakeOrders.AsQueryable ... бесконечный цикл ...

var query = mockedContext.Orders.AsQueryable(); // Infinite loop 
query = FakeOrders.AsQueryable(); // Infinite loop 
query = new List<Order>().AsQueryable(); // Infinite loop 

Как я могу сделать, чтобы только макет DbSet < Заказать>.AsQueryable конкретно, без насмешек IEnumerable < Заказать> .AsQueryable используя IgnoreInstance?

Спасибо за вашу помощь :)

ответ

0

Хорошо, я наконец-то нашел обходной путь:

Я не устраивать DbContext с IgnoreInstance, но я устраиваю конструктор моего DbContext подкласса при вызове с определенной строки подключения в качестве аргумента:

string myConnectionString = "CoreDBTestConnection"; 

// Arrange all CoreDataRepositoryContext instances for this connection string 
Mock.Arrange(() => new CoreDataRepositoryContext(myConnectionString).Returns(GetMockContext()); 

Конструктор заменяется на GetMockContext(), который извлекает изрекленный контекст:

private static CoreDataRepositoryContext GetMockContext() 
{ 
     CoreDataRepositoryContext mockContext = new CoreDataRepositoryContext(); 

     Mock.Arrange(() => mockContext.SaveChanges()).DoNothing(); 

     Mock.Arrange(() => mockContext.Set<Order>()).ReturnsCollection(FakeOrders); 
     Mock.Arrange(() => mockContext.Orders).ReturnsCollection(FakeOrders); 
     Mock.Arrange(() => mockContext.Orders.Add(Arg.IsAny<Order>())).DoInstead((Order o) => FakeOrders.Add(o)); 
     Mock.Arrange(() => mockContext.Orders.Remove(Arg.IsAny<Order>())).DoInstead((Order o) => FakeOrders.Remove(o)); 
     Mock.Arrange(() => mockContext.Orders.Find(Arg.IsAny<object[]>())).Returns((object[] param) => FakeOrders.Find(x => x.Id == (Guid)param[0])); 
     Mock.Arrange(() => mockContext.Orders.AsQueryable()).Returns(() => FakeOrders.AsQueryable()); 

     // Then arrange all DbSets... 

     return mockContext; 
} 

public static FakeDataList<Order> FakeOrders = new List<Order>(); 
+0

Возможно, вы захотите попробовать [JustMock.EntityFramework] (http://www.nuget.org/packages/JustMock.EntityFramework/), чтобы сэкономить много работы. –

0

Вы можете просто удалить IgnoreInstance() из последней договоренности. Это заставит его работать только при вызове этого свойства Orders.

Хотя, технически, вам не нужно размещать какие-либо из этих методов на свойстве Orders. ReturnsCollection позаботится обо всех IList<T> и всех IQueryable<T> методах к цели (если цель реализует любой из этих интерфейсов). Поскольку FakeOrders является списком, то Add и Remove по адресу Orders будут проксироваться по тем же методам в коллекции поддержки. AsQueryable - это не метод экземпляра, а метод расширения. Таким образом, вы не можете издеваться над определенным производным типом, но вам даже не нужно этого делать. Исходная реализация AsQueryable достаточно гибкая, поэтому вам не нужно вообще издеваться над ней.

Если вы просто удалите последние три устройства, ваш тест по-прежнему будет работать должным образом.

+0

Спасибо за ваш help Stephan, – Valone

+0

Спасибо за помощь Стефана. На самом деле, в зависимости от логики бизнес-уровня моего приложения, я должен использовать 'IgnoreInstance'. На самом деле я пытаюсь проверить _Managers_, которые создают новый _Repository_, а затем новый «CoreDataRepositoryContext» каждый раз, когда им нужно получить доступ к базе данных. Таким образом, я размещаю «CoreDataRepositoryContext» независимо от экземпляра метода _ClassInitialize_ моего тестового класса для охвата всех тестов. Я попытался упорядочить свойство 'Orders' без каких-либо методов, но он не работает, и моя база данных запрашивается при вызове этих методов. – Valone

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

  • Нет связанных вопросов^_^