如何将Model类中的Model值传递给Controller类中的Action方法

时间:2015-05-21 11:39:18

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

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

我正在学习Nunit和Nsu​​bstitue,我不知道如何将我在测试用例方法中模拟的Model值传递给我的控制器方法。

以下是我在控制器类中的方法:

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:

[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错了,你能否给我一个如何为上述方法编写TestCase的建议(public ActionResult Manage(string id))

1 个答案:

答案 0 :(得分:2)

  

我不知道,如何传递Model值

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

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

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

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

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

这允许您创建IModelFactory的Stubbed / Mocked / Substituted实现并将其注入您正在测试的控制器/其他类中。所以,你的测试可能会开始这样的事情:

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;

您还需要考虑一下您要测试的内容。通过提取依赖关系,您可以专注于控制器中的逻辑,并将测试集中在该逻辑上。当你开始使用Mocks进入你实际上根本没有测试任何东西的情况时,这是非常容易的,除了你是否正确设置了Mocks。请记住,它们可以帮助您重现强制生产代码遵循特定流程所需的特定方案,而不是替换生产代码中包含的逻辑。