Reputation: 13416
I have an object that is used a bunch of times within the same unit test, and in other unit tests within the same class, that is defined as follows:
private readonly Task<HttpResponseMessage> successfulResponse = Task.FromResult(
new HttpResponseMessage()
{
StatusCode = System.Net.HttpStatusCode.OK,
Content = new StringContent(@"{""EntitySets"":[{""ResultSets"":[{""Results"":[{""Type"":""Message""}],""Total"":2}],""EntityType"":""Message""}]}")
});
Then in each of my relevant unit tests, I'm doing something like this:
mockHttpClient.Setup(m => m.SendAsync(It.Is<HttpRequestMessage>(v =>
v.RequestUri.Host.Equals("example.com")),
It.IsAny<CancellationToken>())).Returns(successfulResponse);
... where mockHttpClient
is a mocked HttpClient
.
But when I'm unit testing, this sort of logic is executed in a lot of places inside the code being tested:
using (HttpResponseMessage response = await this.client.SendAsync(request, cancellationToken))
{
//...
}
... where this.client
is mockHttpClient
from above. As you can tell, Moq
provides my pre-prepared successfulResponse
object here to simulate a http response.
Problem is, when the very first execution of such a using
statement is executed, it disposes successfulResponse
when it gets out of the using
block, and all following using
blocks fail with the following exception:
Test method TestProbe_Success threw exception:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Http.StringContent'.
So my question is, how can I prevent the code being tested from disposing this object, which is used multiple times within the same unit test and in other unit tests ?
Upvotes: 0
Views: 1237
Reputation: 247283
The issue is that you are using a shared resource in your tests, that, if disposed by one test, will cause unwanted effects in another.
Change it to a function
private readonly Func<Task<HttpResponseMessage>> successfulResponse = () => Task.FromResult(
new HttpResponseMessage() {
StatusCode = System.Net.HttpStatusCode.OK,
Content = new StringContent(@"{""EntitySets"":[{""ResultSets"":[{""Results"":[{""Type"":""Message""}],""Total"":2}],""EntityType"":""Message""}]}")
});
and have the setup use the delegate in its Returns
mockHttpClient
.Setup(m => m.SendAsync(It.Is<HttpRequestMessage>(v =>
v.RequestUri.Host.Equals("example.com")
),
It.IsAny<CancellationToken>())
)
.Returns(() => successfulResponse());
That way each time a response is returned, a new instance is used.
Upvotes: 3