如何集成测试一个控制器,在该控制器内部,方法从另一个站点获取令牌。

3
我正在设置一个API,它通过JWT向另一个服务器进行身份验证。我想测试控制器中的一个方法,该方法从外部网站获取令牌。如何测试此方法?
我创建了一个测试服务器,并尝试模拟提供令牌的网站操作。我可以通过测试方法访问Test服务器,但我无法从实际控制器访问它。
以下是我的测试服务器设置方法:MockedController是应该提供令牌并且正常工作的控制器,我可以从测试单元获得令牌。AuthController是应该进行测试的控制器。
var server = new TestServer(
                new WebHostBuilder()
                .UseEnvironment(TestConstants.EnvironmentName)
                .UseStartup<Startup>()
                .UseUrls(TestConstants.MockAddress)
                .ConfigureTestServices(config =>
                {
                    config.AddOptions();
                    config.AddMvc()
                       .SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_2)
                        .AddApplicationPart(typeof(AuthController).Assembly)
                        .AddApplicationPart(typeof(MockedTokenController).Assembly)
                        ;

                    config.AddSingleton<MockedTokenController>();
                    config.BuildServiceProvider();
                }));
            server.BaseAddress = new Uri(TestConstants.MockAddress);
            server.CreateHandler();
            _client = server.CreateClient();
            _client.BaseAddress = new Uri(TestConstants.MockAddress);// I tried with and without this line

以下是测试方法失败的代码:

 var request = new HttpRequestMessage(HttpMethod.Get, "/Auth/Login");
            var response = await _client.SendAsync(request);
            var contents = await response.Content.ReadAsStringAsync();
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);

这是AuthController登录方法的代码

[HttpGet("Login")]
public async Task<IActionResult> LoginAsync(){
         var token = await _authService.GetAuthenticationTokenAsync();
         return Ok(token);
}

这里是AuthService的代码,它从AuthController中被调用。
public async Task<string> GetAuthenticationTokenAsync(){
      HttpClient client = new HttpClient();
       var response = await client.SendAsync(request, 
       HttpCompletionOption.ResponseContentRead);
       response.EnsureSuccessStatusCode();
       var token = await response.Content.ReadAsStringAsync();
       return token;
}

额外信息。 模拟控制器的测试方法运作良好。 看起来问题在于使用模拟控制器的第二步。第一步正常工作。我的意思是我可以在测试单元中从第一步访问模拟控制器,但当我尝试通过主控制器(AuthController)访问它时,我无法访问它。


代码与实现关注点耦合过于紧密,无法允许组件被模拟以使其与第三方依赖项隔离。由于 HttpClient 是手动创建的,因此无法替换其处理程序以伪造请求。您是否考虑过模拟身份验证服务本身? - Nkosi
1个回答

2
你的代码与实现问题紧密耦合,无法允许组件被模拟以使其与第三方依赖项隔离。因为HttpClient是手动创建的,所以无法替换其处理程序以模拟请求。
考虑模拟注入到正在测试的控制器中的身份验证服务本身。"Original Answer"翻译成"最初的回答"
For example

//...

var token = "{fake token here}";
var authService = Mock.Of<IAuthService>(_ =>
    _.GetAuthenticationTokenAsync == Task.FromResult(token)
);

config.AddSingleton<IAuthService>(authService);

//...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接