有没有其他方法可以在mvc中对业务逻辑进行单元测试

本文关键字:业务 单元测试 方法 其他 mvc 有没有 | 更新日期: 2023-09-27 17:54:23

我手动为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);
    }
}

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

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);
    }
}

下一个代码是我治疗的实际单元测试,它不起作用,请给我一些指导。我在谷歌上搜索了很多东西,但还是没能把它做好。

[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());
    }
}

有没有其他方法可以在mvc中对业务逻辑进行单元测试

因此,您正在实例化ITreatmentRepository的mock,设置一些行为并将其注入到TreatmentBusiness类中。到目前为止,一切都很好。

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

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

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

在这种情况下,您的方法应该是这样的:

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);
    }
}

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

根据Jimmy_keen的建议,为了确保您的存储库在整个类中正确实例化并可访问,建议使用工厂。

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

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

这改变了你访问存储库的方式,比如:

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

如果您觉得这太过于严厉,可以选择方法委托(Func<>(,并只注入一个实例化新TreatmentRepository的方法。

这会像这样改变你的构造函数:

public class TreatmentBusiness
{
    private readonly Func<TreatmentRepository> getTreatmentRepository;
    public TreatmentBusiness(Func<TreatmentRepository> getTreatmentRepository)
    {
            this.getTreatmentRepository = getTreatmentRepository;
    }
    ....
}

你可以这样改变你的方法:

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

解决依赖关系的方法取决于您,要么手动执行,要么在实例化业务对象时像这样注入委托:

var treatmentBusiness = new TreatmentBusiness(() => new TreatmentRepository());

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