如何模拟任务<>结果?

时间:2014-05-01 15:23:09

标签: c# task-parallel-library rhino-mocks

我正在设置一些单元测试并使用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,并断言用一个特定的参数调用了一个方法。

1 个答案:

答案 0 :(得分:56)

最简单的方法就是返回一个包含预期结果的已完成任务:

var responseTask = Task.FromResult(response);

我想这个悬挂的原因是模拟的任务永远不会启动,因此给定的func不会运行。你可以在测试中启动它:

var responseTask = MockRepository.GenerateMock<Task<HttpResponseMessage>>(taskFunc);
responseTask.Start();

但是没有理由模拟任务,因为您可以直接轻松创建已完成/失败/取消的任务。