Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Mock a Task<> Result?

I'm setting up some unit tests and using Rhino Mocks to populate the object being tested. One of the things being mocked is a Task<HttpResponseMessage>, since the logic being tested includes a call to an HttpClient to get an async response.

So I've started setting up the mocks like this:

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); 

(The "act" step of the test will be to instantiate the object being tested, feed it the httpClient, and run a method on it. The "assert" will verify via the mocks that expected method calls were made on them.)

Stepping through this in a debugger, there's an indefinite hang on this line:

responseTask.Stub(t => t.Result).Return(response); 

I don't have a lot of experience with Rhino Mocks or with C# async, so I may be overlooking something obvious. The goal, of course, is that any call to the .Result property would return the response mock. But it looks like my attempt itself is perhaps invoking .Result which I would expect to wait indefinitely since it's just a mock, perhaps?

What is the right way to arrange this? Essentially I need to supply my object with a mocked HttpClient and assert that a method was called on it with a specific argument.

like image 574
David Avatar asked May 01 '14 15:05

David


People also ask

What is Task FromResult 0?

return Task.FromResult(0); is used to return a Task that was completed synchronously.

How do you mock a method in MOQ?

First, we instantiate the FakeDbArticleMock class and indicate which setup we want to use for this test. Then, it is necessary to instantiate the repository we want to test and inject the mock instance into it. Finally, we call the method we are testing and assert the results.


1 Answers

The simplest thing is just to return a completed task with the expected result:

var responseTask = Task.FromResult(response); 

I imagine reason this hangs is that the mocked task is never started and hence the given func is not run. You could start it in your test:

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

However there's no reason to mock tasks since you can easily create completed/failed/cancelled tasks directly.

like image 189
Lee Avatar answered Sep 17 '22 13:09

Lee