首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Azure函数UnitTesting模拟HttpClientFactory

Azure函数UnitTesting模拟HttpClientFactory
EN

Stack Overflow用户
提问于 2021-06-29 00:12:51
回答 1查看 70关注 0票数 1

我正在尝试为azure函数创建一个单元测试,并得到不支持的表达式:在设置/验证表达式中不能使用不可重写的成员。

下面是我的函数

代码语言:javascript
复制
public class EmployeeFunction
    {
        private readonly EmpRepo _repo;

        public EmployeeFunction(EmpRepo repo) 
        {
            _repo = repo;
        }

        [FunctionName("EmployeeFunctionTrigger")]
        public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = "EmployeeFunction/{empName}")] HttpRequest req, string empName, ILogger log)
        {
            //code
            return _repo.GetEmployeeByName(empName);
        }
     }

这是我的存储库,我在其中注入IHttpClientFactory

代码语言:javascript
复制
    public class EmpRepo : IEmpRepo 
    {
        private readonly IHttpClientFactory _httpClientFactory;
        public EmpRepo (IHttpClientFactory clientFactory)
        {
            _httpClientFactory = clientFactory;
        }

         public async Task<Employee> GetEmployeeByName(string name)
         {
            using HttpClient _httpClient = httpClientFactory.CreateClient("EmpClient"){
             //code
          }
     }

这是我的测试。我使用的是Xunit和Moq

代码语言:javascript
复制
public class EmpFunctionTest
{
    [Fact]
        public async Task Http_trigger_should_return_known_string()
        {
            // Arrange  
            var httpClientFactory = new Mock<IHttpClientFactory>();
            var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
            var fixture = new Fixture();

            mockHttpMessageHandler.Protected()
                .Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
                .ReturnsAsync(new HttpResponseMessage
                {
                    StatusCode = HttpStatusCode.OK,
                    Content = new StringContent(fixture.Create<String>()),
                });

            var client = new HttpClient(mockHttpMessageHandler.Object);
            client.BaseAddress = fixture.Create<Uri>();
            httpClientFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);
       
         

            var empRepo= new Mock<EmpRepo>(httpClientFactory.Object);
            empRepo.Setup(o => o.GetEmployeeByName(It.IsAny<string>()))
              // prepare the expected response of the mocked http call
              .ReturnsAsync(new Employee()
              {
                  Name= "Test",
                  ID= 12345,
              })
              .Verifiable();

              var EmpFuc= new EmployeeFunction(empRepo.Object);
            //code for act and assert
}

但是得到了异常

代码语言:javascript
复制
System.NotSupportedException : Unsupported expression: o => o.GetEmployeeByName(It.IsAny<string>())   Non-overridable members (here: EmpRepo.GetEmployeeByName) may not be used in setup / verification expressions.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-29 00:52:09

这是一个XY problem

将接口而不是具体类注入到函数中。

代码语言:javascript
复制
public class EmployeeFunction {
    private readonly IEmpRepo repo;

    public EmployeeFunction(IEmpRepo repo) {
        this.repo = repo;
    }

    [FunctionName("EmployeeFunctionTrigger")]
    public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = "EmployeeFunction/{empName}")] HttpRequest req, string empName, ILogger log) {
        //code
        var x = await repo.GetEmployeeByName(empName);

        //...
    }
}

存储库应该是类型化客户端,而不是注入IHttpClientFactory

代码语言:javascript
复制
public class EmpRepo : IEmpRepo {
    private readonly HttpClient client;

    public EmpRepo (HttpClient client) {
        this.client = client;
        //this.client.BaseAddress = new Uri("api url"); //(optional)
    }

     public async Task<Employee> GetEmployeeByName(string name) {
         //..use client here
    }
 }

并相应地进行配置

代码语言:javascript
复制
builder.Services.AddHttpClient<IEmpRepo, EmpRepo>(c => {
    // c.BaseAddress = new Uri("api url"); // as needed
});

最后,测试应该使用async Task而不是async void

代码语言:javascript
复制
public class EmpFunctionTest {
    [Fact]
    public async Task Http_trigger_should_return_known_string() {
        // Arrange  
        var fixture = new Fixture().Customize(new AutoMoqCustomization());

        Mock<IEmpRepo> empRepo = fixture.Freeze<Mock<IEmpRepo>>();
        empRepo
            .Setup(o => o.GetEmployeeByName(It.IsAny<string>()))
            .ReturnsAsync(new Employee() {
                Name = "Test",
                ID = 12345,
            })
            .Verifiable();

        EmployeeFunction subject = fixture.Create<EmployeeFunction>();

        //...code for act and assert
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68166724

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档