使用NUnit,NSubtitute的Web API的TDD

Mar*_*ino 5 c# asp.net unit-testing nsubstitute asp.net-web-api

我仍然对一些TDD概念以及如何正确实现感到困惑。我正在尝试将其实现用于使用Web API的新项目。我已经阅读了很多,有些文章建议使用NUnit作为测试框架,并建议使用NSubstitute模拟存储库。

我不了解的是,我们可以使用NSubstitute定义所需的预期结果,如果我们要验证代码逻辑,这是否有效?

假设我有一个与Putand Delete方法类似的控制器:

[BasicAuthentication]
public class ClientsController : BaseController
{
   // Dependency injection inputs new ClientsRepository
   public ClientsController(IRepository<ContactIndex> clientRepo) : base(clientRepo) { }

 [HttpPut]
    public IHttpActionResult PutClient(string accountId, long clientId, [FromBody] ClientContent data, string userId = "", string deviceId = "", string deviceName = "")
    {
        var result = repository.UpdateItem(new CommonField()
        {
            AccountId = accountId,
            DeviceId = deviceId,
            DeviceName = deviceName,
            UserId = userId
        }, clientId, data);

        if (result.Data == null)
        {
            return NotFound();
        }

        if (result.Data.Value != clientId)
        {
            return InternalServerError();
        }

        IResult<IDatabaseTable> updatedData = repository.GetItem(accountId, clientId);

        if (updatedData.Error)
        {
            return InternalServerError();
        }

        return Ok(updatedData.Data);
    }

    [HttpDelete]
    public IHttpActionResult DeleteClient(string accountId, long clientId, string userId = "", string deviceId = "")
    {
        var endResult = repository.DeleteItem(new CommonField()
        {
            AccountId = accountId,
            DeviceId = deviceId,
            DeviceName = string.Empty,
            UserId = userId
        }, clientId);

        if (endResult.Error)
        {
            return InternalServerError();
        }

        if (endResult.Data <= 0)
        {
            return NotFound();
        }

        return Ok();
    }

}
Run Code Online (Sandbox Code Playgroud)

我创建了一些像这样的单元测试:

[TestFixture]
    public class ClientsControllerTest
    {
        private ClientsController _baseController;
        private IRepository<ContactIndex> clientsRepository;
        private string accountId = "account_id";
        private string userId = "user_id";
        private long clientId = 123;
        private CommonField commonField;

        [SetUp]
        public void SetUp()
        {
            clientsRepository = Substitute.For<IRepository<ContactIndex>>();
            _baseController = new ClientsController(clientsRepository);
            commonField = new CommonField()
            {
                AccountId = accountId,
                DeviceId = string.Empty,
                DeviceName = string.Empty,
                UserId = userId
            };
        }

        [Test]
        public void PostClient_ContactNameNotExists_ReturnBadRequest()
        {
            // Arrange
            var data = new ClientContent
            {
                shippingName = "TestShippingName 1",
                shippingAddress1 = "TestShippingAdress 1"
            };

            clientsRepository.CreateItem(commonField, data)
                .Returns(new Result<long>
                {
                    Message = "Bad Request"
                });

            // Act
            var result = _baseController.PostClient(accountId, data, userId);

            // Asserts
            Assert.IsInstanceOf<BadRequestErrorMessageResult>(result);
        }

        [Test]
        public void PutClient_ClientNotExists_ReturnNotFound()
        {
            // Arrange
            var data = new ClientContent
            {
                contactName = "TestContactName 1",
                shippingName = "TestShippingName 1",
                shippingAddress1 = "TestShippingAdress 1"
            };

            clientsRepository.UpdateItem(commonField, clientId, data)
                .Returns(new Result<long?>
                {
                    Message = "Data Not Found"
                });

            var result = _baseController.PutClient(accountId, clientId, data, userId);
            Assert.IsInstanceOf<NotFoundResult>(result);
        }

        [Test]
        public void PutClient_UpdateSucceed_ReturnOk()
        {
            // Arrange
            var postedData = new ClientContent
            {
                contactName = "TestContactName 1",
                shippingName = "TestShippingName 1",
                shippingAddress1 = "TestShippingAdress 1"
            };

            var expectedResult = new ContactIndex() { id = 123 };

            clientsRepository.UpdateItem(commonField, clientId, postedData)
                .Returns(new Result<long?> (123)
                {
                    Message = "Data Not Found"
                });

            clientsRepository.GetItem(accountId, clientId)
                .Returns(new Result<ContactIndex>
                (
                    expectedResult
                ));

            // Act
            var result = _baseController.PutClient(accountId, clientId, postedData, userId)
                .ShouldBeOfType<OkNegotiatedContentResult<ContactIndex>>();

            // Assert
            result.Content.ShouldBe(expectedResult);
        }

        [Test]
        public void DeleteClient_ClientNotExists_ReturnNotFound()
        {
            clientsRepository.Delete(accountId, userId, "", "", clientId)
                .Returns(new Result<int>()
                {
                    Message = ""
                });

            var result = _baseController.DeleteClient(accountId, clientId, userId);

            Assert.IsInstanceOf<NotFoundResult>(result);
        }

        [Test]
        public void DeleteClient_DeleteSucceed_ReturnOk()
        {
            clientsRepository.Delete(accountId, userId, "", "", clientId)
                .Returns(new Result<int>(123)
                {
                    Message = ""
                });

            var result = _baseController.DeleteClient(accountId, clientId, userId);

            Assert.IsInstanceOf<OkResult>(result);
        }
    }
Run Code Online (Sandbox Code Playgroud)

查看上面的代码,我是否正确编写了单元测试?我觉得我不确定如何验证控制器中的逻辑。

如果有任何需要澄清的信息,请询问更多信息。