我正在设置一些单元测试并使用Rhino Mocks填充正在测试的对象。被模拟的事情之一是Task<HttpResponseMessage>
,因为被测试的逻辑包括调用HttpClient
以获得异步响应。
所以我开始设置这样的模拟:
var httpClient = MockRepository.GenerateMock<HttpClient>();
var taskFunc = MockRepository.GenerateMock<Func<HttpResponseMessage>>();
var responseTask = MockRepository.GenerateMock<Task<HttpResponseMessage>>(taskFunc);
var response = MockRepository.GenerateMock<HttpResponseMessage>();
httpClient.Stub(c => c.PostAsJsonAsync<IEnumerable<LogMessage>>(Arg<string>.Is.Anything, Arg<IEnumerable<LogMessage>>.Is.Anything)).Return(responseTask);
responseTask.Stub(t => t.Result).Return(response);
response.Stub(r => r.IsSuccessStatusCode).Return(true);
(测试的“act”步骤是实例化被测试的对象,将其提供给httpClient
,并在其上运行一个方法。“assert”将通过模拟验证预期的方法调用是在他们身上制作的。)
在调试器中单步执行此操作,这一行无限期挂起:
responseTask.Stub(t => t.Result).Return(response);
我没有很多使用Rhino Mocks或使用C#异步的经验,所以我可能会忽略一些显而易见的事情。当然,目标是对.Result
属性的任何调用都将返回response
模拟。但看起来我的尝试本身可能正在调用.Result
我希望无限期等待,因为它只是一个模拟,也许?
安排这个的正确方法是什么?基本上我需要为我的对象提供一个模拟的HttpClient
,并断言用一个特定的参数调用了一个方法。
答案 0 :(得分:56)
最简单的方法就是返回一个包含预期结果的已完成任务:
var responseTask = Task.FromResult(response);
我想这个悬挂的原因是模拟的任务永远不会启动,因此给定的func不会运行。你可以在测试中启动它:
var responseTask = MockRepository.GenerateMock<Task<HttpResponseMessage>>(taskFunc);
responseTask.Start();
但是没有理由模拟任务,因为您可以直接轻松创建已完成/失败/取消的任务。