【发布时间】:2014-05-01 15:23:08
【问题描述】:
我正在设置一些单元测试并使用 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);
(测试的“行为”步骤将实例化正在测试的对象,向其提供httpClient,并在其上运行一个方法。“断言”将通过模拟验证是否进行了预期的方法调用在他们身上。)
在调试器中单步执行,这一行无限期挂起:
responseTask.Stub(t => t.Result).Return(response);
我对 Rhino Mocks 或 C# async 没有太多经验,所以我可能忽略了一些明显的东西。当然,目标是任何对.Result 属性的调用都将返回response 模拟。但看起来我的尝试本身可能正在调用.Result,我希望它可以无限期地等待,因为它只是一个模拟,也许?
安排这个的正确方法是什么?本质上,我需要为我的对象提供一个模拟的 HttpClient 并断言使用特定参数调用了一个方法。
【问题讨论】:
-
大约一年前,我使用 MOQ 对 Tasks 做了很多模拟。除非我错了,否则你只需要替换你传递给你的模拟 responseTask 的 taskFunc。然后让该模拟函数立即返回响应。
-
@Keith:很有趣。所以只需创建一个真正的
Func<HttpResponseMessage>而不是一个只返回的模拟吗?我只是这样尝试:Func<HttpResponseMessage> taskFunc = delegate() { return response; };并将taskFunc传递给responseTask模拟,但观察到相同的行为。 -
我认为您不需要实际的模拟任务。您需要 Mock 的是传递给 Task 的函数,因此它只会返回“x”。
标签: c# task-parallel-library rhino-mocks