I'm still confused with some TDD concepts and how to do it correctly. I'm trying to use it implement for a new project using Web API. I have read a lot about it, and some article suggest NUnit as a testing framework and NSubstitute to mock the repository.
What I don't understand is with NSubstitute we can define the expected result of what we want, is this valid if we want to validate our code logic?
Let's say I have a controller like this with Put
and Delete
method:
[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();
}
}
and I create some unit tests like this:
[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);
}
}
Looking at the code above, am I writing my unit tests correctly? I feel like I'm not sure how it will validate the logic in my controller.
Please ask for more information, if there is anything that needs clarified.