如何在 RequestScope 中测试 Ninject Factory returns 相同的实例
How to test a Ninject Factory returns the same instance in RequestScope
在 WebApi 应用程序中,我使用 Ninject 注入一个工厂,该工厂允许使用 类 创建一个根据他们的要求确定范围的 DbContext
。我希望能够编写一个单元测试来验证对请求范围上下文 return 同一实例的同一工厂的两次调用。
工厂界面为:
public interface IContextFactory
{
IMyContext GetContext();
IMyContext GetTransientContext();
}
Ninject 配置如下所示:
Bind<IContextFactory>().ToFactory();
Bind<IMyContext>().To<MyContext>()
.InRequestScope()
.NamedLikeFactoryMethod((IContextFactory f) => f.GetContext());
Bind<IMyContext>().To<MyContext>()
.InTransientScope()
.NamedLikeFactoryMethod((IContextFactory f) => f.GetTransientContext());
我的单元测试如下:
[Fact]
public void RequestScopedContextAlwaysSame()
{
// Arrange
NinjectWebCommon.Start();
var factory = (IContextFactory)NinjectWebCommon.Bootstrapper.Kernel.GetService(typeof(IContextFactory));
//Act
var context1 = factory.GetContext();
var context2 = factory.GetContext();
//Assert
Assert.Same(context1, context2);
}
我预计对工厂的两次调用都会 return 同一个实例,但实际上它们是两个不同的实例。我认为这是应用程序中的测试错误,我已经能够成功验证在调用 GetContext()
方法时将同一实例注入不同的消费者。
我怀疑这在单元测试中不起作用,因为没有 HttpContext
并且 InRequestScope()
依赖它。有办法解决这个问题吗?
I suspect this is not working in a unit test because there is no
HttpContext and InRequestScope() depends on it.
我认为你是对的。你可以试试 :
Bind<IMyContext>().To<MyContext>()
.InScope(ctx => this.Scope)
.NamedLikeFactoryMethod((IContextFactory f) => f.GetContext());
其中 this.Scope
是您的测试 class 的 属性 (任何引用类型都可以),其值在您的测试设置时初始化
或者,如果您仍想使用 InRequestScope 语法,您可以尝试:
public class MyPlugin : INinjectHttpApplicationPlugin
{
private Object Scope { get; } = true;
public void Dispose(){}
public INinjectSettings Settings { get; set; }
public object GetRequestScope(IContext context)
{
return Scope;
}
public void Start() { }
public void Stop() { }
}
那么您的测试将类似于:
public void RequestScopedContextAlwaysSame()
{
var kernel = new StandardKernel();
kernel.Components.Add<INinjectHttpApplicationPlugin, MyPlugin>();
kernel.Bind<IContextFactory>().ToFactory();
kernel.Bind<IMyContext>().To<MyContext>()
.InRequestScope()
.NamedLikeFactoryMethod((IContextFactory f) => f.GetContext());
kernel.Bind<IMyContext>().To<MyContext>()
.InTransientScope()
.NamedLikeFactoryMethod((IContextFactory f) => f.GetTransientContext());
var factory = kernel.Get<IContextFactory>();
//Act
var context1 = factory.GetContext();
var context2 = factory.GetContext();
//Assert
Assert.IsTrue(context1.Equals(context2));
}
在 WebApi 应用程序中,我使用 Ninject 注入一个工厂,该工厂允许使用 类 创建一个根据他们的要求确定范围的 DbContext
。我希望能够编写一个单元测试来验证对请求范围上下文 return 同一实例的同一工厂的两次调用。
工厂界面为:
public interface IContextFactory
{
IMyContext GetContext();
IMyContext GetTransientContext();
}
Ninject 配置如下所示:
Bind<IContextFactory>().ToFactory();
Bind<IMyContext>().To<MyContext>()
.InRequestScope()
.NamedLikeFactoryMethod((IContextFactory f) => f.GetContext());
Bind<IMyContext>().To<MyContext>()
.InTransientScope()
.NamedLikeFactoryMethod((IContextFactory f) => f.GetTransientContext());
我的单元测试如下:
[Fact]
public void RequestScopedContextAlwaysSame()
{
// Arrange
NinjectWebCommon.Start();
var factory = (IContextFactory)NinjectWebCommon.Bootstrapper.Kernel.GetService(typeof(IContextFactory));
//Act
var context1 = factory.GetContext();
var context2 = factory.GetContext();
//Assert
Assert.Same(context1, context2);
}
我预计对工厂的两次调用都会 return 同一个实例,但实际上它们是两个不同的实例。我认为这是应用程序中的测试错误,我已经能够成功验证在调用 GetContext()
方法时将同一实例注入不同的消费者。
我怀疑这在单元测试中不起作用,因为没有 HttpContext
并且 InRequestScope()
依赖它。有办法解决这个问题吗?
I suspect this is not working in a unit test because there is no HttpContext and InRequestScope() depends on it.
我认为你是对的。你可以试试 :
Bind<IMyContext>().To<MyContext>()
.InScope(ctx => this.Scope)
.NamedLikeFactoryMethod((IContextFactory f) => f.GetContext());
其中 this.Scope
是您的测试 class 的 属性 (任何引用类型都可以),其值在您的测试设置时初始化
或者,如果您仍想使用 InRequestScope 语法,您可以尝试:
public class MyPlugin : INinjectHttpApplicationPlugin
{
private Object Scope { get; } = true;
public void Dispose(){}
public INinjectSettings Settings { get; set; }
public object GetRequestScope(IContext context)
{
return Scope;
}
public void Start() { }
public void Stop() { }
}
那么您的测试将类似于:
public void RequestScopedContextAlwaysSame()
{
var kernel = new StandardKernel();
kernel.Components.Add<INinjectHttpApplicationPlugin, MyPlugin>();
kernel.Bind<IContextFactory>().ToFactory();
kernel.Bind<IMyContext>().To<MyContext>()
.InRequestScope()
.NamedLikeFactoryMethod((IContextFactory f) => f.GetContext());
kernel.Bind<IMyContext>().To<MyContext>()
.InTransientScope()
.NamedLikeFactoryMethod((IContextFactory f) => f.GetTransientContext());
var factory = kernel.Get<IContextFactory>();
//Act
var context1 = factory.GetContext();
var context2 = factory.GetContext();
//Assert
Assert.IsTrue(context1.Equals(context2));
}