C# 调用.Netcore API的.Netcore控制器的单元测试用例
我想写一个.net核心MVC控制器的单元测试用例。控制器调用.net核心API 我可以模拟IHttpHelper,但它总是返回null。 我有我的IHttpHelperC# 调用.Netcore API的.Netcore控制器的单元测试用例,c#,asp.net-core-mvc,moq,asp.net-core-2.0,xunit.net,C#,Asp.net Core Mvc,Moq,Asp.net Core 2.0,Xunit.net,我想写一个.net核心MVC控制器的单元测试用例。控制器调用.net核心API 我可以模拟IHttpHelper,但它总是返回null。 我有我的IHttpHelper public interface IHttpHelper { Task<HttpResponseMessage> GetAsync(string apiUrl); Task<HttpResponseMessage> PutAsync(string apiUrl, HttpContent
public interface IHttpHelper
{
Task<HttpResponseMessage> GetAsync(string apiUrl);
Task<HttpResponseMessage> PutAsync(string apiUrl, HttpContent content);
Task<HttpResponseMessage> PostAsync(string apiUrl, HttpContent content);
Task<HttpResponseMessage> DeleteAsync(string apiUrl);
}
但是
不返回
HttpResponseMessage
。它返回null
,这就是我的测试用例失败的原因。测试失败的原因很多
被测控制器混合了异步和阻塞调用,如.Result
var jsonData = response.Content.ReadAsStringAsync().Result;
这会导致死锁
参考文献
操作应该始终是异步的
public async Task<IActionResult> ValidateSiteCodes(SiteCodeInputsViewModel siteCodeInputs) {
if (ModelState.IsValid) {
var values = new Dictionary<string, string> {
{"sourceSiteCode", siteCodeInputs.SourceSiteCode.Sitecode},
{"targetSiteCode", siteCodeInputs.TargetSiteCode.Sitecode}
};
var content = new FormUrlEncodedContent(values);
var clientTransferValoidateSiteCodesApiUrl = $"api/wcfctu/validatesitecodes";
HttpResponseMessage response = await _httpHelper.PostAsync(clientTransferValoidateSiteCodesApiUrl, content);
if (response.IsSuccessStatusCode) {
var jsonData = await response.Content.ReadAsStringAsync();
return Ok(jsonData);
}
}
return BadRequest(ModelState);
}
为了保持这种异步,测试方法也应该是异步的
[Fact]
public async Task ValidateSiteCodes_IfValid() {
//...
}
并等待测试中的方法
//Act
var result = await _controller.ValidateSiteCodes(siteCodeInputsViewModel);
为什么要使用
async()=>{await Task.Yield();
?这不仅没有用,异步lambda很可能是问题所在。只需使用()=>responseMessage
或者如果需要()=>Task.FromResult(responseMessage)
我也尝试过()=>Task.FromResult(responseMessage)但我得到了相同的结果。
var jsonData = response.Content.ReadAsStringAsync().Result;
public async Task<IActionResult> ValidateSiteCodes(SiteCodeInputsViewModel siteCodeInputs) {
if (ModelState.IsValid) {
var values = new Dictionary<string, string> {
{"sourceSiteCode", siteCodeInputs.SourceSiteCode.Sitecode},
{"targetSiteCode", siteCodeInputs.TargetSiteCode.Sitecode}
};
var content = new FormUrlEncodedContent(values);
var clientTransferValoidateSiteCodesApiUrl = $"api/wcfctu/validatesitecodes";
HttpResponseMessage response = await _httpHelper.PostAsync(clientTransferValoidateSiteCodesApiUrl, content);
if (response.IsSuccessStatusCode) {
var jsonData = await response.Content.ReadAsStringAsync();
return Ok(jsonData);
}
}
return BadRequest(ModelState);
}
_mockHttpHelper
.Setup(_ => _.PostAsync(It.IsAny<string>(), It.IsAny<HttpContent>()))
.ReturnsAsync(responseMessage);
[Fact]
public async Task ValidateSiteCodes_IfValid() {
//...
}
//Act
var result = await _controller.ValidateSiteCodes(siteCodeInputsViewModel);