Sis*_*hus 2 c# unit-testing factory
我有一个像下面这样的DataService类
public class LessonDataService
{
IUnitOfWork unitOfWork = UnitOfWorkFactory.CreateUnitOfWork();
public Lesson FindById(int id)
{
try
{
return unitOfWork.Lessons.FindById(id);
}
catch (Exception ex)
{
throw exception;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,UnitOfWork是在DataService类中构造的.我也不希望通过构造函数传递UnitOfWork,我不希望UI代码打扰UnitOfWork我只是想让它调用DataService类并让它完成剩下的工作.有任何想法吗?
如何对依赖于Factory的代码进行单元测试
简答:你没有.
紧密耦合的代码很难测试.(但并非不可能).
通过构造函数注入重构代码以显式依赖.(避免服务定位器反模式)
public class LessonDataService : ILessonDataService {
private readonly IUnitOfWork unitOfWork;
public LessonDataService(IUnitOfWork unitOfWork) {
this.unitOfWork = unitOfWork;
}
public Lesson FindById(int id) {
try {
return unitOfWork.Lessons.FindById(id);
} catch (Exception ex) {
throw exception;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不希望UI代码打扰UnitOfWork我只是想让它调用DataService类并让它完成剩下的工作.
然后抽象服务,将其注入UI并让其完成剩下的工作.用户界面不应直接与UOW有关.
public interface ILessonDataService {
Lesson FindById(int id);
}
Run Code Online (Sandbox Code Playgroud)
通过重构依赖于显式抽象,代码现在更加灵活,可以在最小的负面影响下进行单独测试.
[TestMethod]
public void DataService_Should_Get_Lesson() {
//Arrange
var id = 1;
var lesson = new Lesson {
Id = id,
//...code removed for brevity
};
var mock = new Mock<IUnitOfWork>();
mock.Setup(_ => _.Lessons.FindById(id)).Returns(lesson);
var sut = new LessonDataService(mock.Object);
//Act
var actual = sut.FindById(id);
//Assert
lession.Should().BeEquivalentTo(actual);
}
Run Code Online (Sandbox Code Playgroud)
在生产代码中,当前工厂仍然可以在组合根中注册DI容器,但仍然保持代码解耦.
例如(在.Net Core中)
services.AddTransient<IUnitOfWork>(_ => UnitOfWorkFactory.CreateUnitOfWork());
services.AddTransient<ILessonDataService, LessonDataService>();
Run Code Online (Sandbox Code Playgroud)