在Castle.Windsor工厂方法中使用Moq抛出

时间:2018-01-22 08:20:02

标签: c# moq castle-windsor

在Castle.Windsor(v4.1.0)的工厂方法中使用Moq(v4.8.1)时遇到问题。我想知道是否有其他人遇到过这个,以及他们为解决这个问题做了什么。

我有一个简单的界面定义为:

interface IFoo
{
    Task DoFooAsync(Bar bar);
}

在我的主项目中,我在WindsorContainer中注册了以下内容:

container
    .Register(Component.For<IFoo, Foo>()
    .LifestyleTransient());

这在运行时很好地解决了。

在我的测试项目中,我执行以下操作:

container.Register(Component.For<IFoo>().UsingFactorymethod(() => {
    var mock = new Mock<IFoo>();
    mock
        .Setup(x => x.DoFooAsync(It.IsAny<Bar>()))
        .Returns(() => Task.FromResult(true));
    return mock.Object;
})
.IsDefault());

使用来自Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.ApplyCommissionConcerns(对象实例)的消息在测试期间失败:

&#34; 无法将佣金问题应用于组件Late Bound MyAssembly.IFoo,因为它似乎是无目标代理。目前不支持这些。&#34;

注意:&#39; IsDefault()&#39;是只有在那里使Castle.Windsor覆盖主项目的注册,它与此问题无关(我尝试没有它运行,问题仍然存在)。

如果我改为做以下事情:

// exact same code as above, just placed outside the factory method
var mock = new Mock<IFoo>();
mock
    .Setup(x => x.DoFooAsync(It.IsAny<Bar>()))
    .Returns(() => Task.FromResult(true));

// different registration
container
    .Register(Component.For<IFoo>()
    .Instance(mock.Object).IsDefault());

然后一切正常。但现在我的IFoo实例在每次IFoo解析时都会重复使用 - 这与我的主项目中的行为不同,因此不太理想。

我已经查看了Castle.Windsor代码,以了解发生了什么,但没有取得真正的成功。

3 个答案:

答案 0 :(得分:1)

Moq内部使用Castle的动态代理,而模拟类实际上是Castle生成的代理,这是Castle的开发人员不想支持的内部原因。你可以在这里阅读更多内容:

https://github.com/castleproject/Windsor/issues/224

https://github.com/castleproject/castle-youtrack-export/blob/master/IOC/IOC-332.xml

正如Nkosi已经评论过的那样,你应该考虑一下你真正需要实现的目标并重新考虑你的设计。

答案 1 :(得分:0)

&#34;每次IFoo解决时我都会重复使用我的IFoo实例 - 这与我的主项目中的行为不同,因此不太理想。&#34;

用lambda创建属性怎么样?类似的东西:

private IFoo TheMock => CreateMock();
private IFoo CreateMock()
{
   var mock = new Mock<IFoo>();
   mock
    .Setup(x => x.DoFooAsync(It.IsAny<Bar>()))
    .Returns(() => Task.FromResult(true));
   return mock.Object;
}

然后注册

container
.Register(Component.For<IFoo>()
.Instance(TheMock).IsDefault());

免责声明:Haven未对此进行测试,因为我不使用Castle.Windsor。

答案 2 :(得分:0)

这对我有用。 UsingFactoryMethod()失败了。它使用Nsubstitute进行假注射。

var blobservice = Substitute.For<IBlobFileService>();           
RegisterFakeServiceInstance(blobservice);
private void RegisterFakeServiceInstance<TService>(TService fakeService) where TService : class
{
    IocManager.IocContainer.Register(
    Component.For<TService>()
           .Instance(fakeService)
           .LifestyleSingleton()
    );
 }