c# - 还有另一种方法可以在 mvc 中对业务逻辑进行单元测试

标签 c# unit-testing asp.net-mvc-5 moq repository-pattern

我已手动将单元测试添加到 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());
    }
}

最佳答案

所以你正在实例化 ITreatmentRepository 的模拟,设置一些行为并将其注入(inject)您的 TreatmentBusiness类(class)。到目前为止,一切都很好。

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

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

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 的建议,为了确保您的存储库在整个类中被正确实例化和访问,建议使用工厂。

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

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

如果您觉得这太笨重,您可以选择方法委托(delegate) (Func<>) 并仅注入(inject)一个实例化新的 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
    {
        ...
    }
}

解决该依赖关系的方式取决于您,您可以手动执行并在实例化您的业务对象时像这样注入(inject)该委托(delegate):

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

或者您可以使用现有的众多 IoC 容器/DI 框架之一。

关于c# - 还有另一种方法可以在 mvc 中对业务逻辑进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30725638/

相关文章:

java - 如何在 try-with-resource block 中模拟变量

jquery - 提交ajax表单时MVC 5模型属性为空

asp.net-mvc-4 - GoogleOauth2 问题获取内部服务器 500 错误

c# - 如何使用 Asp.Net MVC C# 创建 CMS 应用程序

c# - 将 native DLL 路径添加到托管控制台应用程序

c++ - 谷歌模拟 : Mock private variable member that is instantiated in target class's constructor

c# - 未使用OWIN承载 token 对用户登录进行身份验证

c# - 将其调用并用作 stub 或模拟是否正确?

c# - Request.Url.Query 和 Request.QueryString 有什么区别?

c# - 预期异常断言