我想單元測試我的Web API控制器。我的一個操作方法(POST)有一個問題,它需要從Request
對象中獲取值,以獲取控制器名稱。 我使用NSubtitute,FluentAssertions支持我的單元測試Web API單元測試的模擬請求對象
這是我的控制器代碼如下所示:
public class ReceiptsController : BaseController
{
public ReceiptsController(IRepository<ReceiptIndex> repository) : base(repository) { }
..... Other action code
[HttpPost]
public IHttpActionResult PostReceipt(string accountId, [FromBody] ReceiptContent data, string userId = "", string deviceId = "", string deviceName = "")
{
if (data.date <= 0)
{
return BadRequest("ErrCode: Save Receipt, no date provided");
}
var commonField = new CommonField()
{
AccountId = accountId,
DeviceId = deviceId,
DeviceName = deviceName,
UserId = userId
};
return PostItem(repository, commonField, data);
}
}
和基類爲我的控制器:
public abstract class BaseController : ApiController
{
protected IRepository<IDatabaseTable> repository;
protected BaseController(IRepository<IDatabaseTable> repository)
{
this.repository = repository;
}
protected virtual IHttpActionResult PostItem(IRepository<IDatabaseTable> repo, CommonField field, IContent data)
{
// How can I mock Request object on this code part ???
string controllerName = Request.GetRouteData().Values["controller"].ToString();
var result = repository.CreateItem(field, data);
if (result.Error)
{
return InternalServerError();
}
string createdResource = string.Format("{0}api/accounts/{1}/{2}/{3}", GlobalConfiguration.Configuration.VirtualPathRoot, field.AccountId,controllerName, result.Data);
var createdData = repository.GetItem(field.AccountId, result.Data);
if (createdData.Error)
{
return InternalServerError();
}
return Created(createdResource, createdData.Data);
}
}
這是我的單元測試成功創建場景:
[Test]
public void PostClient_CreateClient_ReturnNewClient()
{
// Arrange
var contentData = TestData.Client.ClientContentData("TestBillingName_1");
var newClientId = 456;
var expectedData = TestData.Client.ClientData(newClientId);
clientsRepository.CreateItem(Arg.Any<CommonField>(), contentData)
.Returns(new Result<long>(newClientId)
{
Message = ""
});
clientsRepository.GetItem(accountId, newClientId)
.Returns(new Result<ContactIndex>(expectedData));
// Act
var result = _baseController.PostClient(accountId, contentData, userId);
// Asserts
result.Should().BeOfType<CreatedNegotiatedContentResult<ContactIndex>>()
.Which.Content.ShouldBeEquivalentTo(expectedData);
}
我不喜歡不知道是否有任何方法從控制器中提取Request對象,或者有什麼方法在單元測試中嘲笑它? 眼下這段代碼Request.GetRouteData()
在單元測試返回null
。
這不是做到這一點的最好辦法。依賴注入是更推薦的方法。 – realnero
但是,它是一個適合我的要求嗎?因爲我只需要它來獲取控制器名稱。也許你可以給出一些代碼示例,因爲我認爲它沒有用,只需要傳遞'''Request'''對象就可以創建一個接口。但是再一次,這只是我的看法,如果你能用一些新的信息給我啓發,我會非常感激。 –
它不僅適用於請求對象,還可以封裝其他依賴項,就像您爲ControllerContext所做的一樣。當你的控制器變得複雜它會更容易維護 – realnero