2014-05-03 3 views
5

Я новичок в обеих библиотеках, и перед тем, как перейти к их использованию в большом проекте, мне нужно уточнить мои варианты автозапуска с низким уровнем кода в моих модульных тестах.Automocking with LightInject plus Nsubstitute, как?

Проведя некоторое время в Google, я пришел к выводу, что для LightInject + Nsubstitute не доступна готовая библиотека плагинов, в отличие от некоторых других пакетов IOC/Mocking, для упрощения объявления недействительных дефолтов по умолчанию этап единичного теста.

Я прочитал документы LightInject о том, как переопределить контейнер LightInject с временным расширенным макетным объектом только для области единичного теста , но как насчет всех отключений изоляции по умолчанию, которые могут быть затронуты модульным тестом. Есть ли способ автоматизировать их создание в контейнере LightInject?

Внутреннее поведение контейнера МОК я ищу это:

public class LightInject.ServiceContainer 
{ 
.. 

    public T GetInstance<T) 
    { 
    if ((this.RegisteredInterfaces.Any(i => i.Itype == T) == false) 
    && (this.TemporaryUnitTestOverrides.Any(i => i.Itype == T) == false)) 
    && (/* this container is configured with an automocking delegate */)) 
      return autoMockCreatorDelegate<T>.Invoke(); 
    } 

Похоже IProxy LightInject и перехватчики обеспечивают некоторые внутренние имитировал объект строительных блоков, но библиотека Nsubstitute является полнофункциональной по сравнению.

Уточнение того, что я имею в виду по умолчанию, не делайте ничего ложного и улучшенного макета.

// default do nothing mock 
    var calculator = Substitute.For<ICalculator>(); 

    // Enhanced mock that will return 3 for .Add(1,2) 
    var calculator = Substitute.For<ICalculator>(); 
    calculator.Add(1, 2).Returns(3); 

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

ответ

8

Я автор LightInject и хотел бы помочь вам.

Позвольте мне изучить это и вернуться к вам. Тем временем вы можете захотеть проверить эту библиотеку на LightInject.AutopMoq, который является третьим лицом в контейнере LightInject. Он использует Moq вместо NSubstitute, но общая концепция должна быть похожа на то, о чем вы просите.

Это было сказано, что я немного поработал некоторое время назад, что еще более упростило автопиляцию и посмотрит на нее и посмотрит, как это можно интегрировать с NSubstitute.

Редактировать

Это супер простая реализация automocking, которая работает с любыми рамками «заменить».

using System.Diagnostics; 
using LightInject;  
using NSubstitute; 

public interface IFoo { } 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var serviceContainer = new ServiceContainer(); 
     serviceContainer.RegisterFallback((type, s) => true, request => CreateMock(request.ServiceType));    
     var foo = serviceContainer.GetInstance<IFoo>(); 
     Debug.Assert(foo is IFoo); 
    } 

    private static object CreateMock(Type serviceType) 
    { 
     return Substitute.For(new Type[] { serviceType }, null);            
    } 
} 

С наилучшими пожеланиями

Bernhard Richter

+0

@bernhard Благодарим за быстрый и авторитетный ответ, ваш примерный код - это именно тот тип решения, на который я надеялся. Я создам несколько прототипов модульных тестов и отчитаюсь здесь. – camelCase

1

Некоторые отзывы, как было обещано в моем комментарии к принятому ответу. Я применил предложение автора LightInject с успехом в некоторых простых модульных тестах.

После того, как я начал работать с основами, я решил скрыть служебный код настройки Ioc в базовом классе плюс то, что я назвал MockingContext, конечным результатом является более чистый код теста более легкого блока. Класс смешного контекста также гарантирует, что заданный макет Neubstitute, настроенный макетным типом, переданный службе Ioc в качестве краткосрочного переопределения automock, существует соответствующий вызов LightInjet.Service.EndMocking (T). Это устраняет опасность того, что сконфигурированные издевательства могут загрязнить автомодельные предположения следующего модульного теста.

В примере ClassC зависит от IFooA и IFooB (без инъекции конструктора). Для единичного теста ниже IFooA автоматически высмеивается LightInject без явного кода, тогда как IFooB настраивается с помощью вызова Nsubstitute, а также передается LightInject в методе MockingContext.Add <>().

[TestClass] 
public class UnitTest1 : AutoMocking 
{ 
    [TestMethod] 
    public void Test_1() 
    { 
     using (var mc = MockingContext) 
     { 
      // No need to mention IFooA here, LightInject will auto mock 
      // any interface not previously declared to it. 

      // Given 
      var mockB = mc.Add<IFooB>(); 
      mockB.MethodY().Returns("Mock Value OOO"); 
      var sut = new ClassC(); 

      // When 
      var testResult = sut.MethodZ(); 

      // Then 
      Assert.AreEqual(testResult, "MethodZ() received=Mock Value OOO"); 
     } 
    } 
+0

Отлично! Было бы очень приятно, если бы вы могли делиться классом MockingContext, чтобы будущие читатели могли его использовать :) – seesharper

+0

@seesharper - Да, как только проблема будет решена, которую я должен был затронуть как проблему на вашем основном сайте Light Inject. Дальнейшее тестирование показало, что LightInjet.Service.EndMocking() не работает, и вручную издевались объекты, истекающие кровью, в следующий модульный тест. Возможно, EndMocking() путается, когда автомощь действует (RegisterFallback), и нет ранее определенного конкретного зарегистрированного типа для службы, чтобы восстановить назад? Это не является серьезным препятствием, потому что я исправил в службе LightInject сервис в моем методе удаления MockingContext. – camelCase

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