2015-04-02 14 views
1

Класс C#, который я хочу протестировать, принимает экземпляры IEnumerable того же интерфейса. Я использую Ninject для инъекции зависимостей. Как бы я впрыснуть издевается INTO в IEnumerable, используя Ninject MockingKernel MoqИспользование Ninject MockingKernel Moq как добавить несколько mocks для одного и того же интерфейса

public class Foo: IFoo 
{ 
    private readonly Dictionary<ContextType, IBar> _bars; 
    public Foo(IEnumerable<IBar> bars) 
    { 
     _bars= bars.ToDictionary(x => x.ContextType); 
    } 
} 
public interface IBar 
{ 
    ContextType ContextType { get; } 
    void DoStuff(); 
} 
public enum ContextType 
{ 
    Local, 
    Site, 
    Test 
} 

Это как мои регулярные вяжущие выглядит как

//assume _kernel is StandardKernel 
_kernel.Bind<IFoo>().To<MyFoo>(); 
_kernel.Bind<IBar>().To<Bar1>(); //ContextType.Site 
_kernel.Bind<IBar>().To<Bar2>(); //ContextType.Local 
_kernel.Bind<IBar>().To<Bar3>(); //ContextType.Test 

Настройка издевается как ниже впрыскивает только последний макет в Foo (как предполагается впрыскивание 3 шт.)

//using _kernel = new MoqMockingKernel() 
_kernel.Bind<IFoo>().To<MyFoo>(); 
var bar1Mock = _kernel.GetMock<IBar>();barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site); 
var bar2Mock = _kernel.GetMock<IBar>();barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local); 
var bar3Mock = _kernel.GetMock<IBar>();barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test); 

_foo = _kernel.Get<IFoo>(); 

Любая помощь приветствуется. Спасибо

+0

При привязке дважды к тому же интерфейсу вы на самом деле _overriding_ previous binding, а не добавление нового. Так что, фактически, тип «Bar3» будет создан при разрешении «IBar» в любом месте кода. Можете ли вы объяснить более четко, чего вы пытаетесь достичь? – Yura

+0

У меня есть шаблон стратегии, реализованный с использованием свойства ContextType IBar в качестве ключа. Итак, я добавляю несколько стратегий (Bars) в Foo и хотел бы вводить макеты для каждой стратегии во время тестирования. – JRT

ответ

0

Почему бы просто не создать экземпляр Foo вручную, если вы тестируете устройство?

var bar1Mock = _kernel.GetMock<IBar(); 
barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site); 
var bar2Mock = _kernel.GetMock<IBar>(); 
barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local); 
var bar3Mock = _kernel.GetMock<IBar>(); 
barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test); 

// simply create new instance, what is a point o 
var target = new Foo(new[]{barMock1.Object, bar2Mock.Object, bar3Mock.Object }); 

Но если правильно Вас понял, вы хотите IEnumerable<IBar> bars быть заполнена Ninject? Затем нужно связать фактическую коллекцию с помощью Ninject:

var allBars = new []{new Bar1(), new Bar2(), new Bar3()}; 
kernel.Bind<IEnumerable<IBar>>().ToConstant(allBars); 

Или попробуйте на самом деле массив IBar вместо IEnumerable<IBar> и оставьте связывание как:

_kernel.Bind<IFoo>().To<MyFoo>(); 
_kernel.Bind<IBar>().To<Bar1>(); //ContextType.Site 
_kernel.Bind<IBar>().To<Bar2>(); //ContextType.Local 
_kernel.Bind<IBar>().To<Bar3>(); 

public class Foo: IFoo 
{ 
    private readonly Dictionary<ContextType, IBar> _bars; 
    public Foo(IBar[] bars) 
    { 
     _bars= bars.ToDictionary(x => x.ContextType); 
    } 
} 

Согласно manual, это должно работать ,

Update: Bind фактических фиктивных экземпляров, и после того, как Resolve IFoo как обычно:

var bar1Mock = _kernel.GetMock<IBar(); 
barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site); 
var bar2Mock = _kernel.GetMock<IBar>(); 
barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local); 
var bar3Mock = _kernel.GetMock<IBar>(); 
barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test); 

_kernel.Bind<IBar>().ToConstant(bar1Mock.Object); 
_kernel.Bind<IBar>().ToConstant(bar2Mock.Object); 
_kernel.Bind<IBar>().ToConstant(bar3Mock.Object); 

foo = _kernel.Get<IFoo>(); 

Update2: Попробуйте этот способ

_kernel.Bind<IBar>().ToMethod(x => bar1Mock.Object); 
_kernel.Bind<IBar>().ToMethod(x => bar2Mock.Object); 
_kernel.Bind<IBar>().ToMethod(x => bar3Mock.Object); 
+0

Я мог бы просто создать экземпляр Foo вручную, но я бы хотел, чтобы Ninject справился с этим. Также иронически создавая новый Foo вручную, передавая в массив barMock.Objects 1, 2 и 3 - не работает. Все три были из последнего типа теста – JRT

+0

Любой успех с конструктором 'IBar [] bars'? – Yura

+0

Я могу использовать ninject для ввода немощных Bar1, Bar2 и Bar3. Там нет проблем, но мне нужно ввести 3 mockBars – JRT

0

Я это работает. _kernel необходимо сбросить до того, как будет запрошен другой уникальный макет того же интерфейса. Этот код ниже работает

var bar1Mock = _kernel.GetMock<IBar();barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site); 
_kernel.Reset(); 

var bar2Mock = _kernel.GetMock<IBar>();barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local); 
_kernel.Reset(); 

var bar3Mock = _kernel.GetMock<IBar>(); barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test); 
_kernel.Reset(); 

_kernel.Bind<IBar>().ToConstant(bar1Mock.Object); 
_kernel.Bind<IBar>().ToConstant(bar2Mock.Object); 
_kernel.Bind<IBar>().ToConstant(bar3Mock.Object); 

Благодарности

0

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

Использование kernel.Reset(); не кажется правильным.

код как

var bar1Mock = _kernel.GetMock<IBar() 
barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site); 
var bar2Mock = _kernel.GetMock<IBar>(); 
barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local); 
var bar3Mock = _kernel.GetMock<IBar>(); 
barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test); 

_kernel.Bind<IBar>().ToMethod(x => bar1Mock.Object); 
_kernel.Bind<IBar>().ToMethod(x => bar2Mock.Object); 
_kernel.Bind<IBar>().ToMethod(x => bar3Mock.Object); 

foo = _kernel.Get<IFoo>(); 

Еще возвращает ссылку на тот же (последний) издеваться. Может, я что-то упустил?

Я хочу использовать насмешливое ядро, но до сих пор лучший, что я получил это:

var barMock1 = new Moq.Mock<IBar>(); 
barMock1.Setup(m=>m.ContextType).Returns(ContextType.Site); 

var barMock2 = new Moq.Mock<IBar>(); 
barMock2.Setup(m=>m.ContextType).Returns(ContextType.Local); 

var bar1Mock3 = new Moq.Mock<IBar>(); 
barMock3.Setup(m=>m.ContextType).Returns(ContextType.Test); 

_kernel.Bind<IBar>().ToMethod(s => barMock1.Object); 
_kernel.Bind<IBar>().ToMethod(s => barMock2.Object); 
_kernel.Bind<IBar>().ToMethod(s => barMock3.Object); 

Это должно работать на более или менее простые объекты, но если есть зависимости в Ибара мы должны разрешить вручную и использовать ninject для этого. Итак, какие-нибудь лучшие идеи, как заставить разные объекты издеваться или каким-то образом установить «область»?

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

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