我有一个 IUnitOfWork 接口,该接口封装了我的自定义存储库。我的自定义存储库又继承自 IRepository 界面。
// The class that I am attempting to unit test
// EmployeeBusiness.cs
private readonly IUnitOfWork _unitOfWork;
public EmployeeBusiness(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public EmployeeDto AddEmployee(EmployeeDto employeeDto)
{
var employee = Mapper.Map<Employee>(employeeDto);
if (employee == null) return null;
_unitOfWork.Employees
.Add(employee);
_unitOfWork.Complete();
return Mapper.Map<EmployeeDto>(employee);
}
// IUnitOfWork interface
public interface IUnitOfWork : IDisposable
{
IEmployeeRepository Employees { get; }
void Complete();
}
// IEmployeeRepository interface
public interface IEmployeeRepository : IRepository<Employee> { }
// IRepository<T> interface
public interface IRepository<TEntity> where TEntity : class
{
void Add(TEntity entity);
// I have added other methods for simplicity
}
我正在尝试对AddEmployee()
方法进行单元测试,因为出现此错误:
该模拟对象预期被调用一次,但被调用0次:uow => uow.Employees.Add(Employee) 配置的设置: IUnitOfWork uow => uow.Employees.Add(员工) 执行的调用: IRepository`1.Add(Employee)
这是我的单元测试
[SetUp]
public void SetUp()
{
_employeeDto = new EmployeeDto
{
FirstName = "John",
LastName = "Smith",
BirthDate = new DateTime(1965, 12, 31)
};
_employee = new Employee
{
FirstName = "John",
LastName = "Smith",
BirthDate = new DateTime(1965, 12, 31)
};
_unitOfWork = new Mock<IUnitOfWork>();
Mapper.Initialize(cfg =>
{
cfg.AddProfile<EmployeeProfile>();
});
}
[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
_unitOfWork.Setup(uow => uow.Employees.Add(_employee));
_employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);
_employeeBusiness.AddEmployee(_employeeDto);
_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once);
_unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}
答案 0 :(得分:2)
您的答案在您的答案中提供的测试(下面复制)通过的原因是您的答案失败了,这是因为您的答案是希望使用您正在使用的特定参考变量(在本例中为_employee)调用该模拟。也许您希望Moq和.Verify()使用.equals()而不是==来检查是否相等?
在被测方法的上下文中,这是正确且理想的-基于测试的名称,您只是想测试该方法确实将您的输入映射到Employee并调用存储库的add方法。如果要确保数据不会在映射中丢失,可以使用It.Is(),它带有一个函数,可用于断言输入的质量(例如,与期望值匹配的名称)。 / p>
如果您只是想测试映射是否成功,则可能对Automapper Configuration Validation作为单独的测试感兴趣。
[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
_unitOfWork.Setup(uow => uow.Employees.Add(_employee));
_employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);
var result = _employeeBusiness.AddEmployee(_employeeDto);
//_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once); <-- This did not work
_unitOfWork.Verify(uow => uow.Employees.Add(It.IsAny<Employee>()), Times.Once); // <-- After changing this to It.IsAny<Employee>() it worked
_unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}
答案 1 :(得分:0)
通过更改单元测试,我设法使其正常工作
[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
_unitOfWork.Setup(uow => uow.Employees.Add(_employee));
_employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);
var result = _employeeBusiness.AddEmployee(_employeeDto);
//_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once); <-- This did not work
_unitOfWork.Verify(uow => uow.Employees.Add(It.IsAny<Employee>()), Times.Once); // <-- After changing this to It.IsAny<Employee>() it worked
_unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}
有人可以帮助我了解使用It.IsAny<Employee>()
和_employee
变量的区别吗?
更新
可以在Thorin's answer上找到说明。
答案 2 :(得分:-2)
您没有检查AddEmployee
的返回值。
[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
_unitOfWork.Setup(uow => uow.Employees.Add(_employee));
_employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);
var result = _employeeBusiness.AddEmployee(_employeeDto);
Assert.IsNotNull(result); // <---
_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once);
_unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}