未调用C#mock(Moq)方法
我试图测试一个API客户机,但由于某种原因,我并没有看到我的一个内部方法被调用。特别是,似乎从未调用AdminClient.MakeHttpCall(根据我在那里设置的断点)。不确定我在这里遗漏了什么,并且以前使用过Moq ****编辑**** 为了澄清这一点,在GetUserAsync方法中,行未调用C#mock(Moq)方法,c#,moq,C#,Moq,我试图测试一个API客户机,但由于某种原因,我并没有看到我的一个内部方法被调用。特别是,似乎从未调用AdminClient.MakeHttpCall(根据我在那里设置的断点)。不确定我在这里遗漏了什么,并且以前使用过Moq ****编辑**** 为了澄清这一点,在GetUserAsync方法中,行var response=wait MakeHttpCall(HttpMethod.Get,$”/api/customadmin/user/id/{id}),变量response为null,调试器似乎从
var response=wait MakeHttpCall(HttpMethod.Get,$”/api/customadmin/user/id/{id})
,变量response
为null
,调试器似乎从未进入MakeHttpCall
方法
试验方法:
[Fact]
[Trait("Category", "AdminClient")]
public async Task ExpiredToken_OnlyTryToRetrieveAccessTokenOnce()
{
int numNonRetryCalls = 0;
int numRetryCalls = 0;
var config = GetConfig();
var unauthorizedResponse = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
var mock = new Mock<AdminClient>(config);
// Set up initial call that returns unauthorized
mock.Setup(x => x.MakeHttpCallInternal(AdminClient.HttpMethod.Get, It.IsAny<string>(), null, false))
.ReturnsAsync(unauthorizedResponse)
.Callback(() => numNonRetryCalls++);
// Set up retry call that returns unauthorized
mock.Setup(x => x.MakeHttpCallInternal(AdminClient.HttpMethod.Get, It.IsAny<string>(), null, true))
.ReturnsAsync(unauthorizedResponse)
.Callback(() => numRetryCalls++);
var result = await mock.Object.GetUserAsync(1);
Assert.Equal(1, numNonRetryCalls);
Assert.Equal(1, numRetryCalls);
}
[事实]
[特征(“类别”、“管理客户”)]
公共异步任务已过期Token_only trytoreetrieveAccessTokenOnce()
{
int numNonRetryCalls=0;
int numRetryCalls=0;
var config=GetConfig();
var unauthorizedResponse=新的HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
var mock=新的mock(配置);
//设置返回未经授权的初始呼叫
mock.Setup(x=>x.MakeHttpCallInternal(AdminClient.HttpMethod.Get,It.IsAny(),null,false))
.ReturnsAsync(未经授权的响应)
.Callback(()=>numNonRetryCalls++);
//设置返回未经授权的重试呼叫
mock.Setup(x=>x.MakeHttpCallInternal(AdminClient.HttpMethod.Get,It.IsAny(),null,true))
.ReturnsAsync(未经授权的响应)
.Callback(()=>numRetryCalls++);
var result=wait mock.Object.GetUserAsync(1);
Assert.Equal(1,numNonRetryCalls);
Assert.Equal(1,numRetryCalls);
}
AdminClient:
public class AdminClient : IAdminClient
{
public enum HttpMethod
{
Get,
Post,
Put,
Delete
}
private readonly AppMgmtConfig _config;
private HttpClient _httpClient;
public AdminClient(AppMgmtConfig config)
{
_config = config;
InitializeHttpClient().Wait();
}
private async Task InitializeHttpClient()
{
if (_httpClient == null)
{
_httpClient = new HttpClient();
Uri baseUri;
Uri.TryCreate(_config.ManagementAPIUrl, UriKind.RelativeOrAbsolute, out baseUri);
_httpClient.BaseAddress = baseUri ?? throw new ArgumentException("Invalid ManagementAPI URL", "ManagementAPIUrl");
var accessToken = (await _config.GetAccessToken()).AccessToken;
var authHeaderValue = new AuthenticationHeaderValue("Bearer", accessToken);
_httpClient.DefaultRequestHeaders.Authorization = authHeaderValue;
}
}
/// <summary>
/// Get user using the integer ID.
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<CrudOperationResult<DbUser>> GetUserAsync(int id)
{
var response = await MakeHttpCall(HttpMethod.Get, $"/api/customadmin/user/id/{id}");
string contentString = await GetStringContentFromResponseMessage(response);
var result = JsonConvert.DeserializeObject<CrudOperationResult<DbUser>>(contentString);
return result;
}
internal virtual async Task<HttpResponseMessage> MakeHttpCall(HttpMethod httpMethod, string url, HttpContent content = null)
{
try
{
var response = await MakeHttpCallInternal(httpMethod, url, content, false);
response.EnsureSuccessStatusCode();
return response;
}
catch
{
await GetNewAccessToken();
var response = await MakeHttpCallInternal(httpMethod, url, content, true);
response.EnsureSuccessStatusCode();
return response;
}
}
internal virtual async Task<HttpResponseMessage> MakeHttpCallInternal(HttpMethod httpMethod, string url, HttpContent content = null, bool isRetryRequest = false)
{
HttpResponseMessage responseMessage = null;
if (httpMethod == HttpMethod.Get)
{
responseMessage = await _httpClient.GetAsync(url);
}
else if (httpMethod == HttpMethod.Post)
{
responseMessage = await _httpClient.PostAsync(url, content);
}
else if (httpMethod == HttpMethod.Delete)
{
responseMessage = await _httpClient.DeleteAsync(url);
}
return responseMessage;
}
internal async Task GetNewAccessToken()
{
var accessToken = (await _config.GetAccessToken()).AccessToken;
if (!String.IsNullOrEmpty(accessToken))
{
var authHeaderValue = new AuthenticationHeaderValue("Bearer", accessToken);
_httpClient.DefaultRequestHeaders.Authorization = authHeaderValue;
}
}
private async Task<string> GetStringContentFromResponseMessage(HttpResponseMessage message)
{
return await message.Content.ReadAsStringAsync();
}
}
公共类AdminClient:IAdminClient
{
公共枚举HttpMethod
{
得到,
邮递
放,
删除
}
私有只读AppMgmtConfig _config;
私有httpclientu HttpClient;
公共AdminClient(AppMgmtConfig配置)
{
_config=config;
初始化HttpClient().Wait();
}
专用异步任务初始化HttpClient()
{
if(_httpClient==null)
{
_httpClient=新的httpClient();
uribaseuri;
TryCreate(_config.managementapirl,UriKind.RelativeOrAbsolute,out baseUri);
_httpClient.BaseAddress=baseUri??抛出新的ArgumentException(“无效的ManagementAPI URL”、“ManagementAPI URL”);
var accessToken=(wait _config.GetAccessToken()).accessToken;
var authHeaderValue=新身份验证HeaderValue(“承载者”,accessToken);
_httpClient.DefaultRequestHeaders.Authorization=authHeaderValue;
}
}
///
///使用整数ID获取用户。
///
///
///
公共异步任务GetUserAsync(int id)
{
var response=await MakeHttpCall(HttpMethod.Get,$”/api/customadmin/user/id/{id});
string contentString=等待GetStringContentFromResponseMessage(响应);
var result=JsonConvert.DeserializeObject(contentString);
返回结果;
}
内部虚拟异步任务MakeHttpCall(HttpMethod HttpMethod,字符串url,HttpContent=null)
{
尝试
{
var response=wait MakeHttpCallInternal(httpMethod,url,content,false);
response.EnsureSuccessStatusCode();
返回响应;
}
抓住
{
等待GetNewAccessToken();
var response=wait MakeHttpCallInternal(httpMethod,url,content,true);
response.EnsureSuccessStatusCode();
返回响应;
}
}
内部虚拟异步任务MakeHttpCallInternal(HttpMethod HttpMethod,字符串url,HttpContent content=null,bool isRetryRequest=false)
{
HttpResponseMessage responseMessage=null;
if(httpMethod==httpMethod.Get)
{
responseMessage=wait_httpClient.GetAsync(url);
}
else if(httpMethod==httpMethod.Post)
{
responseMessage=wait_httpClient.PostAsync(url、内容);
}
else if(httpMethod==httpMethod.Delete)
{
responseMessage=wait _httpClient.deleteSync(url);
}
返回响应消息;
}
内部异步任务GetNewAccessToken()
{
var accessToken=(wait _config.GetAccessToken()).accessToken;
如果(!String.IsNullOrEmpty(accessToken))
{
var authHeaderValue=新身份验证HeaderValue(“承载者”,accessToken);
_httpClient.DefaultRequestHeaders.Authorization=authHeaderValue;
}
}
私有异步任务GetStringContentFromResponseMessage(HttpResponseMessage消息)
{
返回wait message.Content.ReadAsStringAsync();
}
}
您在mock上进行的设置调用表示,当MoQ看到使用您指定的参数对该方法的调用时,它会执行您告诉它的操作,并返回调用,这将完全阻止调用原始方法。尽管如此,我们还是不清楚您想要实现什么。但是您模拟了该方法,为什么希望调用它?Moq框架通常只是模拟一个第三方对象,您不需要验证其完整性,也不希望得到您所期望的。您没有正确使用它。@Phaeze我在模仿MakeHttpCallInternal
<测试中的code>GetUser
调用MakeHttpCall
(未模拟),然后(在本例中应该)调用两次MakeHttpCallInternal
@Evk我正在模拟MakeHttpCallInternal。测试中的GetUser调用MakeHttpCall(这不是mock),它反过来(在本例中应该)调用两个MakeHttpCallInternal