是否有另一种方法可以在mvc中对业务逻辑进行单元测试

min*_*hle 4 c# unit-testing moq repository-pattern asp.net-mvc-5

我手动为mvc5应用程序添加了单元测试.这是我的业务逻辑

public void AddTreatments(TreatmentView model)
{
    using(var treatment = new TreatmentRepository())
    {
        var treat = new PhysiqueData.ModelClasses.Treatment()
        {
            treatmentID = model.treatmentID,
            treatmentCost = model.treatmentCost,
            treatmentDuration = model.treatmentDuration,
            treatmentName = model.treatmentName
        }
        treatment.Insert(treat);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我在服务层中使用的存储库

public class TreatmentRepository:ITreatmentRepository
{
    private ApplicationDbContext _datacontext;
    private readonly IRepository<Treatment> _treatmentRepository;

    public TreatmentRepository()
    {
        _datacontext = new ApplicationDbContext();
        _treatmentRepository = new RepositoryService<Treatment>(_datacontext);
    }

    public void Insert(Treatment model)
    {
        _treatmentRepository.Insert(model);
    }
}
Run Code Online (Sandbox Code Playgroud)

下一个代码是我对我的治疗的实际单位测试,它不起作用,我可以得到一些指导.我搜索了很多东西,仍然无法做到正确.

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void AddingTreatmenttodatabase()
    {
        //var business = new TreatmentBusiness(new TreatmentRepository());

        var treatment = new Treatment()
        {
            treatmentID = 1,
            treatmentCost = 250,
            treatmentDuration = 45,
            treatmentName = "LowerBack"
        };

        var repositoryMock = new Mock<ITreatmentRepository>();
        repositoryMock.Setup(x => x.Insert(treatment));

        var business = new TreatmentBusiness(repositoryMock.Object);

        business.AddTreatments(treatment);

        repositoryMock.Verify(x => x.Insert(treatment), Times.Once());
    }
}
Run Code Online (Sandbox Code Playgroud)

Yan*_*eus 5

所以你要实例化一个模拟ITreatmentRepository,设置一些行为并将它注入你的TreatmentBusiness类.到现在为止还挺好.

但是,在你的AddTreatments方法中,你实例化一个新的TreatmentRepository,而不是使用通过构造函数注入的那个.

我假设您的构造函数看起来像这样:

public class TreatmentBusiness
{
    private readonly ITreatmentRepository repository;

    public TreatmentBusiness(ITreatmentRepository repository)
    {
        this.repository = repository;
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您的方法应如下所示:

public void AddTreatments(TreatmentView model)
{
    using (var treatment= this.repository)
    {
        var treat = new PhysiqueData.ModelClasses.Treatment();
        {
            treat.treatmentID = model.treatmentID;
            treat.treatmentCost = model.treatmentCost;
            treat.treatmentDuration = model.treatmentDuration;
            treat.treatmentName = model.treatmentName;
        }
        treatment.Insert(treat);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意字段的用法repository,而不是实例化新字段.

根据Jimmy_keen的建议,为了确保您的存储库在整个课程中得到适当的实例化和访问,建议您选择工厂.

有几种方法可以实现存储库工厂,要么手动创建专用工厂并将其注入构造函数,如下所示:

public class TreatmentBusiness
{
    private readonly ITreatmentRepositoryFactory repositoryFactory;

    public TreatmentBusiness(ITreatmentRepositoryFactory repositoryFactory)
    {
        this.repositoryFactory = repositoryFactory;
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

这会改变您访问存储库的方式,如下所示:

public void AddTreatments(TreatmentView model)
{
    using (var treatment= this.repositoryFactory.Make())
    //or whatever method name you've chosen on your factory
Run Code Online (Sandbox Code Playgroud)

如果你觉得这太沉重了,你可以选择一个方法delegate(Func<>)并注入一个实例化new的方法TreatmentRepository.

这将改变你的构造函数,如下所示:

public class TreatmentBusiness
{
    private readonly Func<TreatmentRepository> getTreatmentRepository;

    public TreatmentBusiness(Func<TreatmentRepository> getTreatmentRepository)
    {
            this.getTreatmentRepository = getTreatmentRepository;
    }
    ....
}
Run Code Online (Sandbox Code Playgroud)

你会改变你的方法:

public void AddTreatments(string model)
{
    using (var treatment = this.getTreatmentRepository()) //Or this.getTreatmentRepository.Invoke() - same thing
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

解决该依赖关系的方式取决于您,要么手动执行,要在实例化Business对象时注入该委托:

var treatmentBusiness = new TreatmentBusiness(() => new TreatmentRepository());
Run Code Online (Sandbox Code Playgroud)

或者您可以使用众多IoC容器/ DI框架中的一个.