C#模拟IHttpclient和CreateClient

时间:2019-01-15 13:40:46

标签: c# unit-testing mocking moq xunit

我有一个要进行x单元测试的函数,但似乎必须模拟CreateClient函数?每当我在测试过程中对其进行调试时,似乎var client等于null。我可以肯定地注入依赖项。我想知道的是如何模拟CreateClient。

这是该功能:

    public async Task CreateMessageHistoryAsync(Message message)
    {
        //This seems to be giving a null value
        var client = this.clientFactory.CreateClient(NamedHttpClients.COUCHDB);

        var formatter = new JsonMediaTypeFormatter();
        formatter.SerializerSettings = new JsonSerializerSettings
        {
            Formatting = Formatting.Indented,
            NullValueHandling = NullValueHandling.Ignore,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };

        Guid id = Guid.NewGuid();            

        var response = await client.PutAsync(id.ToString(), message, formatter);

        if (!response.IsSuccessStatusCode)
        {
            throw new HttpRequestException(await response.Content.ReadAsStringAsync());
        }
    }

这是单元测试,我在单独的类中模拟IHttpClient,并且正在使用该类。

    [Collection("MockStateCollection")]
    public class CreateMessageHistory
    {
        private readonly MockStateFixture mockStateFixture;

        public CreateMessageHistory(MockStateFixture mockStateFixture)
        {
            this.mockStateFixture = mockStateFixture;
        }

        [Fact]
        public async Task Should_NotThrowHttpRequestException_When_AMessageHistoryIsCreated()
        {
            var recipients = MockMessage.GetRecipients("Acc", "Site 1", "Site 2", "Site 3");
            var message = MockMessage.GetMessage(recipients);

            mockStateFixture
                .MockMessageHistoryService
                .Setup(service => service.CreateMessageHistoryAsync(message));

            var messageHistoryService = new MessageHistoryService(
                mockStateFixture.MockIHttpClientFactory.Object);

            mockStateFixture.MockIHttpClientFactory.Object.CreateClient("CouchDB");

            var task = messageHistoryService.CreateMessageHistoryAsync(message);
            var type = task.GetType();
            Assert.True(type.GetGenericArguments()[0].Name == "VoidTaskResult");
            Assert.True(type.BaseType == typeof(Task));
            await task;

            //await Assert.IsType<Task>(messageHistoryService.CreateMessageHistoryAsync(message));
            // await Assert.ThrowsAsync<HttpRequestException>(() => messageHistoryService.CreateMessageHistoryAsync(message));
        }
    }

在我看来,我还需要模拟CreateClient类吗?

1 个答案:

答案 0 :(得分:3)

您应该为已设置了LocalizedControlType, ClassNAme and Name方法的AutomationId and RuntimeId注入模拟对象。

ClientFactory

然后,您必须将CreateClient传递给构造函数:

// create the mock client
var httpClient = new Mock<IHttpClient>();

// setup method call for client
httpClient.Setup(x=>x.PutAsync(It.IsAny<string>()
                               , It.IsAny<Message>(),
                               , It.IsAny< JsonMediaTypeFormatter>())
          .Returns(Task.FromResult(new HttpResponseMessage { StatusCode = StatusCode.OK}));

// create the mock client factory mock
var httpClientFactoryMock = new Mock<IHttpClientFactory>();

// setup the method call
httpClientFactoryMock.Setup(x=>x.CreateClient(NamedHttpClients.COUCHDB))
                     .Returns(httpClient);

更新

要对httpClientFactoryMock.Object进行单元测试,因为它没有任何接口,则应按照here所述对其进行包装。

具体来说,我们必须按以下方式安排http客户端:

var messageHistoryService = new MessageHistoryService(httpClientFactoryMock.Object);

现在,当调用HttpClient时,我们应该返回上面的// Mock the handler var handlerMock = new Mock<HttpMessageHandler>(MockBehavior.Strict); handlerMock.Protected() // Setup the PROTECTED method to mock .Setup<Task<HttpResponseMessage>>("PutAsync", ItExpr.IsAny<String>(), ItExpr.IsAny<Message>() ItExpr.IsAny<MediaTypeFormatter>()) // prepare the expected response of the mocked http call .ReturnsAsync(new HttpResponseMessage() { StatusCode = HttpStatusCode.OK }) .Verifiable(); // use real http client with mocked handler here var httpClient = new HttpClient(handlerMock.Object) { BaseAddress = new Uri("http://test.com/"), };

httpClient