Home > Back-end >  Unit testing - mocking service which has a List as a data storage
Unit testing - mocking service which has a List as a data storage

Time:04-12

I'm new to Unit testing and I'm trying to learn how to do it.

I'm using Moq to Mock the dependencies.

Here's my Testing class:

using Microsoft.AspNetCore.Mvc;
using Moq;
using scholarship.Controllers;
using scholarship.Services.Interface;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Xunit;

namespace Testing
{
    public class InternControllerTests
    {
        private Mock<IInternService> _internService = new Mock<IInternService>(); 

        [Theory]
        [InlineData("00000000-0000-0000-0000-000000000001")]
        [InlineData("00000000-0000-0000-0000-000000000002")]
        public void Delete_Intern(Guid id)
        {
            InternsController internsController
                = new InternsController(_internService.Object);

            var actual = internsController.DeleteIntern(id) as ObjectResult;

            Assert.True(actual is OkObjectResult);
        }

        [Theory]
        [InlineData("00000000-0000-0000-0000-000000000000")]
        [InlineData("00000000-0000-0000-0000-000000000005")]
        public void Delete_Intern_NotFound(Guid id)
        {
            InternsController internsController
                = new InternsController(_internService.Object);

            var actual = internsController.DeleteIntern(id) as ObjectResult;

            Assert.True(actual is NotFoundObjectResult);
        }
    }
}

the service:

using scholarship.Models;
using scholarship.Services.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace scholarship.Services.Class
{
    public class InternCollectionService : IInternService
    {
        public static List<Intern> _interns = new List<Intern>
        {
            new Intern { ID = new Guid("00000000-0000-0000-0000-000000000001"), FirstName = "Octavian", LastName = "Niculescu", DateOfBirth=new DateTime(2001,01,01)},
            new Intern { ID = new Guid("00000000-0000-0000-0000-000000000002"), FirstName = "Andrei", LastName = "Popescu", DateOfBirth=new DateTime(2002,01,01)},
            new Intern { ID = new Guid("00000000-0000-0000-0000-000000000003"), FirstName = "Calin", LastName = "David", DateOfBirth=new DateTime(2003,01,01)},
        };
        public bool Create(Intern model)
        {
            _interns.Add(model);
            return true;
        }

        public bool Delete(Guid id)
        {
            int index = _interns.FindIndex(intern => intern.ID == id);
            if (index == -1)
            {
                return false;
            }
            _interns.RemoveAt(index);
            return true;
        }

        public Intern Get(Guid id)
        {
            return (from intern in _interns
                          where intern.ID == id
                          select intern).FirstOrDefault();
        }

        public List<Intern> GetAll()
        {
            return _interns;
        }

        public bool Update(Guid id, Intern model)
        {
            int index = _interns.FindIndex(intern => intern.ID == id);
            if (index == -1)
            {
                return false;
            }
            model.ID = id;
            _interns[index] = model;
            return true;
        }
    }
}

the controller

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using scholarship.Models;
using scholarship.Services.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace scholarship.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class InternsController : ControllerBase
    {
        IInternService _internService;
        public InternsController(IInternService internService)
        {
            _internService = internService ?? throw new ArgumentNullException(nameof(internService));
        }

        [HttpGet]
        public IActionResult GetInterns()
        {
            return Ok(_internService.GetAll());
        }

        [HttpGet("{Id}", Name = "GetIntern")]
        public IActionResult GetIntern([FromRoute] Guid Id)
        {
            Intern? intern = _internService.Get(Id);
            if(intern == null)
            {
                return NotFound();
            }
            return Ok(intern);
        }

        [HttpPost]
        public IActionResult AddIntern([FromBody] Intern intern)
        {
            intern.ID = Guid.NewGuid();
            _internService.Create(intern);
            return CreatedAtRoute("GetIntern", new { ID = intern.ID }, intern);
        }

        [HttpPut("{id}")]
        public IActionResult UpdateIntern([FromBody] Intern intern, Guid id)
        {
            if (intern == null)
            {
                return BadRequest("Intern cannot be null");
            }
            _internService.Update(id, intern);
            return Ok();
        }

        [HttpDelete("{id}")]
        public IActionResult DeleteIntern(Guid id)
        {
            bool deleted = _internService.Delete(id);
            if (deleted == false)
            {
                return NotFound("Intern cannot be found");
            }
            return Ok();
        }
    }
}

The project is a very small one, I used it to start learning .net.

Now I want to learn Unit Testing, and I'm trying to learn Unit Testing.

The Delete tests fail.

I think this happens because by mocking the service, there is no list with data like in the service.

So, how should I make the Delete tests work? Should I somehow mock that list too? (I don't know how)

Thanks.

CodePudding user response:

Although it is not best practice to test everything in one shoot, you can change your code as per below and test by status code with your inline data and hardcoded return type:

    [Theory]
    [InlineData("00000000-0000-0000-0000-000000000001", true, 200)]
    [InlineData("00000000-0000-0000-0000-000000000002", true, 200)]
    [InlineData("00000000-0000-0000-0000-000000000000", false, 404)]
    [InlineData("00000000-0000-0000-0000-000000000005", false, 404)]
    public void Delete_Intern(Guid id, bool expectedReturn, int expectedStatusCode)
    {
        InternsController internsController
            = new InternsController(_internService.Object);

        _internService.Setup(x => x.Delete(It.Is<Guid>(x => x.Equals(id)))).Returns(expectedReturn);

        var actual = internsController.DeleteIntern(id) as ObjectResult;

        Assert.True(actual.StatusCode == expectedStatusCode);
    }

However, you can read the How to use Moq and xUnit for Unit Testing Controllers in ASP.NET Core which I think is a good practice.

  • Related