asp.net-mvc - 如何将模型值从测试类传递到 Controller 类中的操作方法

标签 asp.net-mvc unit-testing testing nunit nsubstitute

我正在为 MVC 应用程序创建一些 Nunit 测试。我正在为我的 Controller 类中的方法编写测试用例。我正在使用 Nsubstitute 模拟对象。

我正在学习 Nunit 和 Nsubstitue,但我不知道如何将在测试用例方法中模拟的模型值传递给我的 Controller 方法。

下面是我在 Controller 类中的方法:

public ActionResult Manage(string id)
{
    var clusterCollections = ReadXml();
    int clusterIndex = clusterCollections.ClusterCollectionList.FindIndex(a => a.ClusterId == id);
    var model = new ClusterManagementModel()
    {
        ClusterNodeDetailsList = BindClusterDetailsToGrid(id),
        DropDownListClusterName = BindClusterNameToDropDown(),
        CurrentClusterId = clusterIndex,
        CurrentClusterName = id,
        HStatus = Hstatus(id),
        IStatus = Istatus(id)
    };
    return View(model);
}

这是我写的测试用例:

[TestCase]
public void TestManage()
{         
    var ManagementController = Substitute.ForPartsOf<ClusterManagementController>();
    var ManagementModel = Substitute.ForPartsOf<ClusterManagementModel>();
    ClusterCollections clusterCollection = new ClusterCollections();
    List<ClusterNodeDetails> ClusterNodes = new List<ClusterNodeDetails>();
    List<DDL_ClusterName> DropDownListClusterName = new List<DDL_ClusterName>();
    ManagementController.ReadXml().Returns(clusterCollection);
    ManagementModel = new ClusterManagementModel()
    {
        ClusterNodeDetailsList = ClusterNodes,
        DropDownListClusterName = DropDownListClusterName,
        CurrentClusterId = 1,
        CurrentClusterName = "UnitTesting",
        HStatus = "True",
        IStatus = "Success"
    };
    var result = ManagementController.Manage("1") as ActionResult;
    Assert.AreEqual(ManagementModel, result);
}

如果我在测试用例方法中有错误,请指正。

如果我的 TestCase 是错误的,你能给我一个建议如何为上面的方法编写一个 TestCase (public ActionResult Manage(string id))

最佳答案

I don't know, how to pass Model value

简短的回答是,在当前形式下,您无法将在测试中创建的模型传递给 Controller ​​。这是人们在第一次尝试对代码进行单元测试时遇到的常见问题。摆脱困境的方法是在开始编写生产代码时考虑到测试。

一种常见的方法是从类中提取依赖项并通过类的构造函数注入(inject)这些依赖项。因此,您可以将模型创建逻辑提取到 ModelFactory 中,并修改您的 Controller 以具有如下构造函数:

public ManagementController(IModelFactory modelFactory) {
    _modelFactory = modelFactory;
}

有各种库可以帮助注入(inject)这些依赖项(Ninject、AutoFac 等)。但是如果你不想/不能使用它们,那么你还需要添加一个默认构造函数来设置你对默认具体实现的依赖:

public ManagementController() {
    _modelFactory = new ModelFactory();
}

这允许您创建 IModelFactory 的 Stubbed/Mocked/Substituted 实现并将其注入(inject)到您的 Controller /其他被测类中。因此,您的测试可能会像这样开始:

List<ClusterNodeDetails> ClusterNodes = new List<ClusterNodeDetails>();
List<DDL_ClusterName> DropDownListClusterName = new List<DDL_ClusterName>();

var model = new ClusterManagementModel()
{
    ClusterNodeDetailsList = ClusterNodes,
    DropDownListClusterName = DropDownListClusterName,
    CurrentClusterId = 1,
    CurrentClusterName = "UnitTesting",
    HStatus = "True",
    IStatus = "Success"
};

var modelFactory = Substitute.For<IModelFactory>();
modelFactory.CreateClusterManagementModel( /* args for model creation */).Returns(model);

var sut = new ManagementController(modelFactory);
var result = sut.Manage("1") as ActionResult;

您还需要考虑要测试的是什么。通过提取依赖项,您可以专注于 Controller 中的逻辑,并将测试重点放在该逻辑上。当您开始使用 Mocks 时,很容易陷入您实际上根本没有测试任何东西的情况,除了您是否正确设置了 Mocks 之外。请记住,它们的存在是为了帮助您重现您需要强制生产代码遵循特定流程的特定场景,而不是替换生产代码中包含的逻辑。

关于asp.net-mvc - 如何将模型值从测试类传递到 Controller 类中的操作方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30372659/

相关文章:

asp.net-mvc - 单元测试和 HttpContext.Current

c# - 新 View 或局部 View

c# - 为什么我的验证消息是通用的? ASP.NET MVC

asp.net-mvc - 调试时编辑 .NET Core cs 文件

javascript - sinon 监视功能不起作用

django - 如何从所有应用程序加载 Django 装置?

c# - .net MVC 使用数据库的简单成员身份验证

android - 单元测试 Retrofit 接口(interface)声明的好方法

c++ - CMake:防止在子目录库项目中构建测试可执行目标

testing - 为什么 Sonar 中需要 Java 二进制文件?