How to unit test ViewBag in ASP.NET Core?
Asked Answered
K

1

6

During writing unit tests for ASP.NET Core application I realized that the ViewData is accessable from ViewResult but ViewBag is not.

My HomeController:

public class HomeController : Controller
{
    private readonly IHeroRepository _heroItems;
    private readonly IQuestRepository _questItems;

    public HomeController(
        IHeroRepository heroItems,
        IQuestRepository questItems)
    {
        _heroItems = heroItems;
        _questItems = questItems;
    }

    [HttpGet]
    public async Task<IActionResult> Index()
    {
        var recentHeroesVM = await _heroItems.GetRecentHeroesAsync(2);
        ViewBag.QuestSelectList = await _questItems.GetSelectListAsync();
        return View(recentHeroesVM);
    }
}

My testing class:

public class HomeController_Index
{
    [Fact]
    public async Task Index_ReturnsAViewResult_WithAListOfRecentHeros()
    {
        // Arrange
        var mockHeroRepo = new Mock<IHeroRepository>();
        var mockQuestRepo = new Mock<IQuestRepository>();
        var recentHerosCount = 2;
        mockHeroRepo.Setup
        (
            repo => repo.GetRecentHerosAsync(recentHerosCount))
                .Returns(Task.FromResult(GetTestItems())
        );
        var controller = new HomeController(mockHeroRepo.Object, mockQuestRepo.Object);

        // Act
        var result = await controller.Index();

        // Assert
        var viewResult = Assert.IsType<ViewResult>(result);

        // No definition error below.
        var questSelectListVB = Assert.IsAssignableFrom<SelectList>(
            viewResult.ViewBag.QuestSelectList);
    }

    private IEnumerable<HeroViewModel> GetTestItems()
    {
        var items = new List<HeroViewModel>
        {
            new HeroViewModel
            {
                Name = "First Hero",
            },
            new HeroViewModel
            {
                Name = "Second Hero",
            },
        };
        return items;
    }
}

Question 1: Why there is no ViewBag property in ViewResult when in the ASP.NET MVC version of ViewResult class there is clearly one (MSDN)?

Question 2: How I am supposed to test the ViewBag when I have no access to it?

Koehler answered 3/8, 2017 at 1:19 Comment(1)
What is type of viewResult? Have you tried to specify type explicitly ViewResult viewResult = Assert.IsType<ViewResult>(result); (and likely get compile time error) ?Bedspring
K
7

Question 1: Still a mystery for me. More like question for Core developers.

Question 2:

"The ViewBag property is a wrapper around ViewData that provides a dynamic view over that collection. It is not a separate collection." - ASP.NET Core Docs

So it is one object. Since there is no ViewBag property in ViewResult (a reminder - we are talking here about Core version), access it in ViewData dictionary style:

var questSelectListVB = Assert.IsAssignableFrom<SelectList>(viewResult.ViewData["QuestSelectList"]);
Koehler answered 23/8, 2017 at 9:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.