c# - Mvc 5 单元测试 - 设置 Controller 的 viewbag 值

标签 c# asp.net-mvc unit-testing asp.net-mvc-5 viewbag

我有一个索引页,它可能有一个 ViewBag 值是上次搜索的值。我想设置我的 Controller ,以便我能够在调用我的被测系统 (ProductManagementController)

之前设置此 ViewBag

索引操作

[HttpPost]
public async Task<ActionResult> Index(ProductManagementVm postedVm)
{
    // Reset pagination if new search
    if (postedVm.BookSearch != ViewBag.lastSearch)
    {
        postedVm.Page = 1;
    }

    var httpResponseMessage = await_httpService.GetAsync(_urlConfigurations.GetProductList);

    var vm = _productFactory.BuildProductManagementVm(
                    await Task.Run(() => httpResponseMessage.Content.ReadAsStringAsync()), postedVm);


    vm.BookSearch = postedVm.BookSearch;

    if (string.IsNullOrEmpty(postedVm.BookSearch))
    {
        postedVm.BookSearch = string.Empty;
    }

    ViewBag.lastSearch = postedVm.BookSearch;
    return View(vm);
}

设置类

using System.ComponentModel.DataAnnotations;
using System.Net.Http;
using System.Web.Mvc;
using ICEBookshop.MVC.App.Controllers;
using ICEBookshop.MVC.App.Interfaces;
using ICEBookshop.MVC.App.Interfaces.Factories;
using ICEBookshop.MVC.App.Models;
using ICEBookshop.MVC.App.Models.ViewModels;
using Moq;
using SpecsFor;

namespace ICEBookshop.MVC.App.Tests.Controllers.ProductManagement
{
    public class BaseGiven : SpecsFor<ProductManagementController>
    {
        protected Mock<IHttpService> HttpServiceMock = new Mock<IHttpService>();
        protected Mock<IProductFactory> ProductFactoryMock = new Mock<IProductFactory>();
        protected Mock<IUrlConfigurations> UrlConfigurationsMock = new Mock<IUrlConfigurations>();
        protected Mock<IJsonValidator> JsonValidatorMock = new Mock<IJsonValidator>();
        protected ProductManagementController ProductManagementController;
        protected HttpResponseMessage HttpResponseMessage;
        protected string JsonContent;
        protected bool IsModelStateValid;  

        protected ActionResult ActionResult;
        protected RedirectToRouteResult RedirectToRouteResult;
        protected ViewResult ViewResult;
        protected ProductManagementVm ProductManagementVm;
        protected ProductViewModel ProductViewModel;   

        protected void BaseGivenSetup()
        {
            ProductManagementController = new ProductManagementController(HttpServiceMock.Object,
                ProductFactoryMock.Object, UrlConfigurationsMock.Object, JsonValidatorMock.Object);

            SUT = ProductManagementController;
        }
    }
}

我想设置 ProductManagementController.ViewBag.SomeName = "some string" 所以当我进入 Controller 时我会测试该场景,但目前它是 null

有谁知道如何在测试之前设置 Controller 的 ViewBag 值?

单元测试

public class WhenServiceReturnProductsAndViewBagHasSearchString : GivenGoingToIndexActionInProductsManagement
{
    protected override void When()
    {
        HttpResponseMessage = new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent("some string content from the service")
        };

        HttpServiceMock.Setup(expr => expr.GetAsync(It.IsAny<string>())).ReturnsAsync(HttpResponseMessage);

        ProductFactoryMock.Setup(
                expr => expr.BuildProductManagementVm(It.IsAny<string>(), It.IsAny<ProductManagementVm>()))
            .Returns(new ProductManagementVm());

        // This doesn't work :(
        SUT.ViewBag.LastSearch = "Hey I'm a search string :D";

        BaseGivenSetup();

        ActionResult = SUT.Index(new ProductManagementVm()).Result;
        ViewResult = (ViewResult)ActionResult;
        ProductManagementVm = (ProductManagementVm)ViewResult.Model;
    }

    [Test]
    public void ThenActionResultIsNotNull()
    {
        Assert.IsNotNull(ActionResult);
    }

    [Test]
    public void ThenAViewResultIsNotNull()
    {
        Assert.IsNotNull(ViewResult);
    }

    [Test]
    public void ThenProductManagementVmIsNotNull()
    {
        Assert.IsNotNull(ProductManagementVm);
    }
}

最佳答案

ViewBagViewData 属性获取数据

public dynamic ViewBag
{
    get
    {
        if (_dynamicViewDataDictionary == null)
        {
            _dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData);
        }
        return _dynamicViewDataDictionary;
    }
}

所以你需要填充你想要的值,以便在 ViewBag

中访问它

这是一个POC

[TestClass]
public class ViewBagTests {
    [TestMethod]
    public void ViewBag_ShouldBe_PrePopulated() {
        //Arrange
        var SUT = new TargetController();

        var expected = "Hey I'm the old search string :D";

        SUT.ViewData["LastSearch"] = expected;

        //Act
        var actual = SUT.Index() as ViewResult;

        //Assert
        Assert.AreEqual(expected, actual.Model);
    }

    class TargetController : Controller {
        public ActionResult Index() {
            var previous = ViewBag.LastSearch;
            return View((object)previous);
        }
    }

}

关于c# - Mvc 5 单元测试 - 设置 Controller 的 viewbag 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43326638/

相关文章:

c# - OpenXmlReader.Skip 应该如何工作?

asp.net - Elasticsearch .net客户端嵌套查询容器始终为null

java - 如何对构造函数进行单元测试

c# - 将旧的 Unity 代码升级到 Unity 5

c# - 代码不会将数组的所有元素插入字符串

c# - LINQ 中的嵌套 GroupBy 扩展方法

c# - Entity Framework : Illegal characters in path.(连接字符串)(MVC3)

c# - ViewModel 最终成为 Model 的副本 - 好处在哪里?

C#单元测试题

angular - 更改模拟服务为 Angular/Jasmine/Redux 中的每个测试返回的可观察值