Search code examples
c#unit-testingasp.net-core-mvcxunitasp.net-core-viewcomponent

.NET CORE MVC ViewComponent xUnit Testing


I have started using xUnit for a sample .NET CORE MVC project and I am struggling with adding tests to a ViewComponent which includes IOptions and IHostingEnvironment. It's a simple view component that returns values from the appsettings.json file and this itself works without issue.

appsettings.json Snippet:

"Application": {"Name": "My App","Version": "1.0.0","Author": "John Doe", "Description": "Just a template!"}

ViewComponent:

[ViewComponent(Name = "Footer")]
public class FooterViewComponent : ViewComponent
{
    private readonly IOptions<AppSettings.Application> _app;
    private readonly IHostingEnvironment _env;

    public FooterViewComponent(IOptions<AppSettings.Application> app, IHostingEnvironment env)
    {
        _app = app;
        _env = env;
    }

    public IViewComponentResult Invoke()
    {
        var vm = new FooterViewModel();
        {
            vm.AppName = _app.Value.Name;
            vm.AppVersion = _app.Value.Version;
            vm.AppEnvironment = _env.EnvironmentName;
        }

        return View(vm);
    }
}

I would like to test that the return type is a ViewComponent result and the View Model is not empty.

ViewComponent Test:

public class FooterViewComponentTest
{
    public class Should
    {
        [Fact]
        public void ReturnViewCompnentWithViewModel()
        {
            // Arrange
            var viewComp = new FooterViewComponent(??????????);

            // Act
            var result = viewComp ??????????;

            // Assert
            Assert.IsType<ViewComponentResult>(result);

        }
    }
}

I'm still working on this and will edit my snippets with my findings. Does anybody have any suggestions and should I be writing the tests in this format?


Solution

  • With the well known Moq Framework you can write mock objects of the dependency abstractions and inject them in the constructor of the component like this:

    public class FooterViewComponentTest
    {
        public class Should
        {
            [Fact]
            public void ReturnViewCompnentWithViewModel()
            {
                // Arrange
                var appSettings = new AppSettings.Application();
                appSettings.AppName = "app";
                appSettings.Version = "1.0";
                var optionsMock = new Mock<IOptions<AppSettings.Application>>();
                optionsMock.Setup(o => o.Value).Returns(appSettings);
    
                var hostingMock = new Mock<IHostingEnvironment>();
                hostingMock.Setup(h => h.Environment).Returns("Test");
    
                var viewComp = new FooterViewComponent(optionsMock.Object, hostingMock.Object);
    
                // Act
                var result = viewComp.Invoke();
    
                // Assert
                Assert.IsType<ViewComponentResult>(result);
    
            }
        }
    }
    

    Reference Moq Quickstart to get a better understanding of how to use the mocking framework.