我需要一个快速入门来测试我的业务层上的方法。考虑Materials BLL对象,我该如何为它测试AddNewMaterial方法?
interface IGenericRepository<TEntity>
{
TEntity Add(TEntity m);
}
public interface IMaterialRepository : IGenericRepository<Material>
{
}
public interface IUnitOfWork
{
IMaterialRepository Materials { get; private set;}
void Save();
}
public interface IUnitOfWorkFactory
{
IUnitOfWork GetUnitOfWOrk();
}
public class MaterialsBLL
{
private readonly IUnitOfWorkFactory _uowFactory;
//uowFactory comes from DI
public MaterialsBLL(IUnitOfWorkFactory uowFactory)
{
_uowFactory = uowFactory;
}
//TODO: test this
public Material AddNewMaterial(Material m)
{
using(var uow = _uowFactory.GetUnitOfWOrk())
{
var result = uow.Materials.Add(m);
uow.Save();
return result;
}
}
我正在使用Moq和XUnit,但我非常环保。一般来说,我想这样做:
在我看来,我可能应该创建一个Fake MaterialRepository,而不是嘲笑它?还有其他建议吗?这是第一次破解:
[Fact]
public void TestGetMaterialById()
{
var materialList = GetMaterials();
var materialRepositoryMock = new Mock<IMaterialRepository>();
materialRepositoryMock.Setup(repo => repo.Get(4)).Returns(materialList.First());
var uowMock = new Mock<IUnitOfWork>();
uowMock.SetupProperty<IMaterialRepository>(uow => uow.Materials, materialRepositoryMock.Object);
var uowFactoryMock = new Mock<IUnitOfWorkFactory>();
uowFactoryMock.Setup(f => f.GetUnitOfWork()).Returns(uowMock.Object);
var materialsBll = new Materials(uowFactoryMock.Object);
var result = materialsBll.Get(4);
Assert.Equal(result.MaterialId, 4);
Assert.Equal(result.Name, "Four");
}
答案 0 :(得分:0)
如果您觉得需要多个级别的嵌套模拟对象,那么您的设计通常会出现问题。
Law of Demeter在此向我们发出警告,您可能不应该修改uow.Materials
中的MaterialsBLL
。
此外,工作单元通常不是公开存储库的地方。需要访问Materials的代码通常直接引用IMaterialsRepository
,而不是从UoW请求它,然后Repository实现可能会在内部引用UoW。
这样可以实现更平坦的设计,简化您的生产代码和测试。