Класс С#, который я хочу протестировать, принимает экземпляры IEnumerable одного и того же интерфейса. Я использую Ninject для инъекции зависимостей. Как я должен вводить mocks в IEnumerable, используя Ninject MockingKernel Moq
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
Настройка mocks, как показано ниже, вводит только последний макет в Foo (как предполагается, впрыскивание 3 mocks)
//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>();
Любая помощь приветствуется. благодаря
Запуск в ту же проблему. Ответы выше не помогли. Ниже приведено одно решение, но оно не идеально.
Использование 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);
Это должно работать для более или менее простых объектов, но если в Ibar есть зависимости, нам придется решать вручную и использовать ninject для этого. Итак, какие-нибудь лучшие идеи, как заставить разные объекты издеваться или каким-то образом установить "область"?
Сейчас у меня это работает. _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);
благодаря
Почему бы просто не создать экземпляр 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);
}
}
Согласно руководству, это должно сработать.
Обновление: привязка к фактическим макетным экземплярам и после разрешения 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>();
Обновление2: попробуйте этот путь
_kernel.Bind<IBar>().ToMethod( x => bar1Mock.Object);
_kernel.Bind<IBar>().ToMethod( x => bar2Mock.Object);
_kernel.Bind<IBar>().ToMethod( x => bar3Mock.Object);
IBar[] bars
?