如何Mock设置方法返回不同值?解决单元测试中HttpClient ObjectDisposedException异常
Let's break down why you're hitting this error and how to fix it quickly:
The Root Cause
Your test creates a single HttpClient instance and tells the mock HttpClientFactory to return that same instance every time CreateClient() is called. But in your production code, both GetResponseAsync and PostReponseAsync wrap their HttpClient usage in a using block.
When the first using block (in GetResponseAsync) finishes, it disposes the shared HttpClient. By the time PostReponseAsync calls CreateClient() again, it gets the already-disposed instance—hence the ObjectDisposedException.
The Fix
Instead of returning the same HttpClient every time, configure the mock HttpClientFactory to return a new HttpClient instance on each CreateClient() call. All these instances will use your pre-configured HttpMessageHandler mock, so your response sequence will still work as expected.
Update your test's Arrange section where you set up the HttpClientFactory:
// Replace this: // var httpClient = new HttpClient(handlerMock.Object); // _mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(httpClient); // With this: _mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())) .Returns(() => new HttpClient(handlerMock.Object));
This way, each using block in your production code gets its own fresh HttpClient instance. Since all instances share the same mocked HttpMessageHandler, your SetupSequence will still return GetResponseMessage for the first request and postResponseMessage for the second.
Quick Notes on Your Production Code
I noticed a couple of small typos that might cause issues later:
- In
CallMethod, you're passingNametoGetResponseAsyncinstead of the method parameteraccountName. - In
PostReponseAsync, you're usingURl(lowercase L) instead ofURL—this will throw a compilation error ifURlisn't defined.
Modified Test Code
Here's the full corrected test method for reference:
[TestMethod] public async Task CallMethod_ReturnsFinalResponse() { // Arrange string accountName = "Value"; var GetResponseMessage = new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent("Message1"), }; var postResponseMessage = new HttpResponseMessage { StatusCode = HttpStatusCode.OK, Content = new StringContent("Message2"), }; var handlerMock = new Mock<HttpMessageHandler>(); handlerMock.Protected().SetupSequence<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>()) .ReturnsAsync(GetResponseMessage) .ReturnsAsync(postResponseMessage); // Updated setup to return new HttpClient each time _mockHttpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())) .Returns(() => new HttpClient(handlerMock.Object)); // Act var response = await _classUnderTest.CallMethod(accountName); // Assert Assert.AreEqual("Message2", response); }
内容的提问来源于stack exchange,提问作者Arshit Singh

