asp.net core 6.0 web api unit test using NUnit

I am trying to create the simple web api test for the controller action method I have in my project. I already create and add the test project in my solution. And add the Nunit nuget package in test project.

The controller I am trying to test is look like this:

[ApiController]
[Route("[controller]")]
public class HomeController : ControllerBase

{
   
    private readonly IConfiguration _configuration;
    private readonly IHostEnvironment _hostEnvironment;
    private readonly ILogger<HomeController> _logger;
    private BaseDataAccess _datatAccess = new BaseDataAccess()
   
    public HomeController(ILogger<HomeController> logger, IConfiguration configuration, IHostEnvironment hostEnvironment)
    {
        _logger = logger;
        _configuration = configuration;
        _hostEnvironment = hostEnvironment;
    }

      
    [HttpGet("GetInfo/{code}")]
    public IActionResult GetInfo(string code)
    {
        List<InfoModel> infos = new List<InfoModel>();

        int isNumber;
        if (String.IsNullOrEmpty(code) || !int.TryParse(code, out isNumber))
        {
            _logger.LogInformation(String.Format("The code pass as arguments to api is : {0}", code));
            
            return BadRequest("Invalid code");
        }

        try
        {
            
            _logger.LogDebug(1, "The code passed is" + code);
            SqlConnection connection = _datatAccess.GetConnection(_configuration, _hostEnvironment);
            string sql = string.Format ("SELECT * from table1 where code={0}", code);
            DataTable dt = _datatAccess.ExecuteQuery(connection,CommandType.Text, sql);

            if (dt != null && dt.Rows.Count > 0)
            {
                foreach (DataRow dr in dt.Rows)
                {
                    infos.Add(new InfoModel
                    {
                        ID = dr["id"].ToString(),
                        code = dr["code"].ToString()
                    });
                }
            }


        }
        catch (Exception ex)
        {
            _logger.LogError(4, String.Format("Error Message: " + ex.Message + "\n" + ex.StackTrace));
            
            return BadRequest("There is something wrong.Please contact the administration.");
        }


        return new OkObjectResult(infos);

    }
}

Now when I try to create the unit test I need to pass the configuration, hostenvironment and logger to HomeController from my TestHomeController. And I don't know how to instantiate these settings and pass to controller:

using NUnit.Framework;
using Microsoft.AspNetCore.Mvc;
using MyApi.Models;
using MyApi.Controllers;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;


namespace MyApi.Tests
{
  [TestFixture]
  public class TestHomeController: ControllerBase
   {
     private readonly IConfiguration _configuration; //How to instantiate this so it is not null
     private readonly IHostEnvironment _hostEnvironment ;//How to instantiate this so it is not null
     private ILogger<HomeController> _logger;//How to instantiate this so it is not null


    [Test]
    public void GetInfo_ShouldReturnAllInfo()
    {

        var controller = new HomeConteoller(_logger, _configuration, _hostEnvironment);
        var result = controller.GetInfo("11");
        var okObjectResult = (OkObjectResult)result;

        //Assert
        okObjectResult.StatusCode.Equals(200);


    }
}

}

Thanks for any help and suggestions.

1 answer

  • answered 2022-03-18 20:13 Maksym

    Probably, you have startup.cs. Don't you? if you gonna test a controller, then you need to build a whole instance of an application. Here I put an example of how you can test your code if you have Startup.cs.

     public class SUTFactory : WebApplicationFactory<Startup>
    {
        protected override IHostBuilder CreateHostBuilder()
        {
            return Program.CreateHostBuilder(null);
        }
    }
    
    public class TestControllerTests
    {
        private SUTFactory factory;
        private HttpClient _client;
        public TestControllerTests() 
        {
            factory = new SUTFactory();
            _client = factory.CreateClient();
        }
    
        [Test]
        public async Task GetPatientInterviewID_ShouldReturnAllInterviewID()
        {
            // Arrange
            var id = "11";
    
            // Act
            var result = await _client.GetAsync($"Home/GetInfo/{id}");
    
            // Assert
            Assert.AreEqual(System.Net.HttpStatusCode.OK, result.StatusCode);
        }
    }
    

    This example is closer to Integration testing rather than Unit-testing. If you want to have unit-test then you need to do the following things

    1. BaseDataAccess _datatAccess this is a specific realization and it cannot be mocked (comparing to ILogger, IHostEnvironment etc)

    2. move all your code from the controller to a separate class, and test this class.

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum