如何编写紧耦合工厂设计模式代码块的Xunit测试用例?
How to write Xunit test case of factory design pattern code block which is tightly coupled?
我想编写以下方法的 xunit 测试用例。您能否建议替代设计,以便我可以在当前项目中以最少的更改编写 xunit 测试用例。
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = ContextFactory.Current.GetDomain<EmployeeDomain>().GetEmployeeFilterAsync(id,
CurrentUser.CompanyId, filter); // Not able write unit test case , please suggest alternate design.
return View("View", response);
}
}
当前设计如下
public interface IDomain
{
}
public interface IContext
{
D GetDomain<D>() where D : IDomain;
string ConnectionString { get; }
}
public class ApplicationContext : IContext
{
public D GetDomain<D>() where D : IDomain
{
return (D)Activator.CreateInstance(typeof(D));
}
public string ConnectionString
{
get
{
return "DatabaseConnection";
}
}
}
public class ContextFactory
{
private static IContext _context;
public static IContext Current
{
get
{
return _context;
}
}
public static void Register(IContext context)
{
_context = context;
}
}
//var response = ContextFactory.Current.GetDomain****().GetEmployeeFilterAsync(id,
公司 ID, 过滤器);
此行用于调用特定的 class 方法,即来自 EmployeeDomain 的 GetEmployeeFilterAsync。虽然它非常方便并且在我们的应用程序中广泛使用但是由于设计问题我无法编写单元
测试用例。
能否请您提出设计建议,以便我们可以用最少的更改编写单元测试用例。
不要使用 Service Locator anti-pattern,而是使用构造函数注入。我不知道 AssetDomain
是什么来自 OP,但似乎重要的是依赖性。将其注入 class:
public class ProbablySomeController
{
public ProbablySomeController(AssetDomain assetDomain)
{
AssetDomain = assetDomain;
}
public AssetDomain AssetDomain { get; }
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = AssetDomain.GetAssetFilterAsync(id, CurrentUser.CompanyId, filter);
return View("View", response);
}
}
}
假设AssetDomain
是一个多态类型,你现在可以编写一个测试并注入一个Test Double:
[Fact]
public void MyTest()
{
var testDouble = new AssetDomainTestDouble();
var sut = new ProbablySomeController(testDouble);
var actual = sut.Index(42, AssetFilterType.All);
// Put assertions here
}
第 1 步:所需的库
第 2 步:当应用程序启动时,注册所需的域,例如
受保护无效Application_Start()
UnityConfig.RegisterComponents();
第 3 步:创建一个静态 class 并注册您所有的域
例子
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
Initialize domain which will injected in controller
container.RegisterType<IPricingDomain, PricingDomain>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
第 4 步:
所以你可以在构造函数中注入相应的接口
在控制器文件中。
目标:摆脱项目中的任何模式。
并开始编写单元测试用例。
我想编写以下方法的 xunit 测试用例。您能否建议替代设计,以便我可以在当前项目中以最少的更改编写 xunit 测试用例。
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = ContextFactory.Current.GetDomain<EmployeeDomain>().GetEmployeeFilterAsync(id,
CurrentUser.CompanyId, filter); // Not able write unit test case , please suggest alternate design.
return View("View", response);
}
}
当前设计如下
public interface IDomain
{
}
public interface IContext
{
D GetDomain<D>() where D : IDomain;
string ConnectionString { get; }
}
public class ApplicationContext : IContext
{
public D GetDomain<D>() where D : IDomain
{
return (D)Activator.CreateInstance(typeof(D));
}
public string ConnectionString
{
get
{
return "DatabaseConnection";
}
}
}
public class ContextFactory
{
private static IContext _context;
public static IContext Current
{
get
{
return _context;
}
}
public static void Register(IContext context)
{
_context = context;
}
}
//var response = ContextFactory.Current.GetDomain**
此行用于调用特定的 class 方法,即来自 EmployeeDomain 的 GetEmployeeFilterAsync。虽然它非常方便并且在我们的应用程序中广泛使用但是由于设计问题我无法编写单元
测试用例。
能否请您提出设计建议,以便我们可以用最少的更改编写单元测试用例。
不要使用 Service Locator anti-pattern,而是使用构造函数注入。我不知道 AssetDomain
是什么来自 OP,但似乎重要的是依赖性。将其注入 class:
public class ProbablySomeController
{
public ProbablySomeController(AssetDomain assetDomain)
{
AssetDomain = assetDomain;
}
public AssetDomain AssetDomain { get; }
public ActionResult Index(int id = 0, AssetFilterType filter = AssetFilterType.All)
{
using (var tracer = new Tracer("AssetController", "Index"))
{
RemoveReturnUrl();
ViewBag.JobId = id;
var response = AssetDomain.GetAssetFilterAsync(id, CurrentUser.CompanyId, filter);
return View("View", response);
}
}
}
假设AssetDomain
是一个多态类型,你现在可以编写一个测试并注入一个Test Double:
[Fact]
public void MyTest()
{
var testDouble = new AssetDomainTestDouble();
var sut = new ProbablySomeController(testDouble);
var actual = sut.Index(42, AssetFilterType.All);
// Put assertions here
}
第 1 步:所需的库
第 2 步:当应用程序启动时,注册所需的域,例如
受保护无效Application_Start()
UnityConfig.RegisterComponents();
第 3 步:创建一个静态 class 并注册您所有的域
例子
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
Initialize domain which will injected in controller
container.RegisterType<IPricingDomain, PricingDomain>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
第 4 步:
所以你可以在构造函数中注入相应的接口 在控制器文件中。
目标:摆脱项目中的任何模式。 并开始编写单元测试用例。