1

テストしたい C# クラスは、同じインターフェイスの IEnumerable インスタンスを受け入れます。依存性注入には Ninject を使用します。Ninject MockingKernel Moqを使用してIEnumerableにモックを挿入するにはどうすればよいですか

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>();

どんな助けでも大歓迎です。ありがとう

4

3 に答える 3

0

同じ問題に直面しています。上記の回答は役に立ちませんでした。以下に 1 つの解決策を示しますが、これは理想的ではありません。

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 を使用することが望ましいでしょう。では、さまざまなオブジェクトのモックを取得する方法や、「スコープ」を設定する方法について、より良いアイデアはありますか?

于 2015-08-07T14:29:55.827 に答える
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 を使用して実際のコレクションをバインドする必要があります。

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>();

Update2:この方法を試してください

_kernel.Bind<IBar>().ToMethod( x => bar1Mock.Object); 
_kernel.Bind<IBar>().ToMethod( x => bar2Mock.Object);
_kernel.Bind<IBar>().ToMethod( x => bar3Mock.Object);
于 2015-04-02T19:33:01.530 に答える