Rog*_*Far 2 c# asp.net-mvc unit-testing moq unity-container
在我正在使用此代码的类中:
public User CurrentUser
{
get
{
var unityContainer = new UnityContainer();
var httpContextHelper = unityContainer.Resolve<HttpContextHelper>();
return httpContextHelper.GetUser();
}
}
Run Code Online (Sandbox Code Playgroud)
这是在Bootstrapper.cs文件中:
public static class Bootstrapper
{
public static void Initialise()
{
IUnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType<IHttpContextHelper, HttpContextHelper>();
DependencyResolver.SetResolver(new UnityDependencyResolver(unityContainer));
}
}
Run Code Online (Sandbox Code Playgroud)
我不能在这里使用构造函数注入,因为它是一个基类,重构需要相当多的工作.
但是我如何对此进行单元测试呢?我找不到合适的模拟方法unityContainer.Resolve.
Dar*_*rov 10
首先,以下代码是错误的:
get
{
var unityContainer = new UnityContainer();
var httpContextHelper = unityContainer.Resolve<HttpContextHelper>();
return httpContextHelper.GetUser();
}
Run Code Online (Sandbox Code Playgroud)
您正在创建一个新的Unity容器,当然它是空的,然后您尝试从此容器中解析一些实例,这些实例只是调用HttpContextHelper该类的默认构造函数.Gosh我讨厌Unity,当你试图解决一个从未注册到容器中的事物的实例时(这就是你在这里做的),不会抛出异常.相反,它默默地使用大多数已知(已注册)的依赖项来调用其构造函数.
因此,这不会返回您在Bootstrapper中注册的实例,因为您有一个不同的UnityContainer实例,您已在其中注册了IHttpContextHelper实例.
因此,重构这一步的第一步是使用DependencyResolver:
public User CurrentUser
{
get
{
var httpContextHelper = DependencyResolver
.Current
.GetService<IHttpContextHelper>();
return httpContextHelper.GetUser();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在单元测试中,您可以编写自定义依赖项解析器:
public class DepepndecyResolverMock : IDependencyResolver
{
private readonly IDictionary<Type, object> kernel;
public DepepndecyResolverMock(IDictionary<Type, object> kernel)
{
this.kernel = kernel;
}
public object GetService(Type serviceType)
{
return this.kernel[serviceType];
}
public IEnumerable<object> GetServices(Type serviceType)
{
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
您可以为测试配置:
var kernel = new Dictionary<Type, object>
{
{ typeof(IHttpContextHelper), new HttpContextHelperMock() }
};
DependencyResolver.SetResolver(new DepepndecyResolverMock(kernel));
Run Code Online (Sandbox Code Playgroud)
话虽这么说,这段代码仍然是非常错误的.它可能允许你对它进行单元测试,但我请坚持,这是错误的设计.不要使用它.这使用了服务定位器模式,这是一种反模式.
执行此操作的正确方法是反转此类的控件,以便它不需要获取其依赖项,但需要将其依赖项注入其中.因此,不要在无用的模式中浪费你的时间,而是重构你的代码,以便它使用真正的依赖注入.