单元测试 - 以列表作为数据存储的模拟服务

Unit testing - mocking service which has a List as a data storage

我是单元测试的新手,我正在努力学习如何做。

我正在使用 Moq 来模拟依赖项。

这是我的测试 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);
        }
    }
}

服务:

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;
        }
    }
}

控制器

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();
        }
    }
}

项目很小,我用它来开始学习.net

现在想学习单元测试,正在努力学习单元测试

删除测试失败。

我认为发生这种情况是因为通过模拟服务,没有像服务中那样包含数据的列表。

那么,我应该如何进行删除测试呢?我是否也应该以某种方式嘲笑该列表? (我不知道如何)

谢谢。

虽然一次性测试所有内容并不是最佳做法,但您可以按照以下更改代码并使用内联数据和硬编码 return 类型通过状态代码进行测试:

    [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);
    }

但是,您可以阅读 How to use Moq and xUnit for Unit Testing Controllers in ASP.NET Core 我认为这是一个很好的做法。