在 Castle.Windsor 工厂方法中使用 Moq 抛出
Using Moq in Castle.Windsor factory method throws
我在 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(对象实例):
"无法将佣金问题应用于组件后期绑定 MyAssembly.IFoo,因为它似乎是无目标代理。目前不支持这些。"= 15=]
注意: 'IsDefault()' 只是为了让 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 代码以了解发生了什么,但没有真正成功。
"my IFoo instance is reused each time IFoo is resolved - which is a different behavior than in my main project, and therfore not desired."
用 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());
免责声明:还没有测试过,因为我不使用 Castle.Windsor。
Moq 在内部使用 Castle 的动态代理和模拟 class 实际上是由 Castle 生成的代理,出于某些内部原因,Castle 的开发人员不想支持。您可以在此处阅读更多信息:
https://github.com/castleproject/Windsor/issues/224
https://github.com/castleproject/castle-youtrack-export/blob/master/IOC/IOC-332.xml
正如 Nkosi 已经评论过的那样,您应该考虑真正需要实现的目标并重新考虑您的设计。
这对我有用。 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()
);
}
我在 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(对象实例):
"无法将佣金问题应用于组件后期绑定 MyAssembly.IFoo,因为它似乎是无目标代理。目前不支持这些。"= 15=]
注意: 'IsDefault()' 只是为了让 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 代码以了解发生了什么,但没有真正成功。
"my IFoo instance is reused each time IFoo is resolved - which is a different behavior than in my main project, and therfore not desired."
用 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());
免责声明:还没有测试过,因为我不使用 Castle.Windsor。
Moq 在内部使用 Castle 的动态代理和模拟 class 实际上是由 Castle 生成的代理,出于某些内部原因,Castle 的开发人员不想支持。您可以在此处阅读更多信息:
https://github.com/castleproject/Windsor/issues/224
https://github.com/castleproject/castle-youtrack-export/blob/master/IOC/IOC-332.xml
正如 Nkosi 已经评论过的那样,您应该考虑真正需要实现的目标并重新考虑您的设计。
这对我有用。 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()
);
}