如何集成测试控制器,在该控制器内部,方法从另一个站点获取令牌
How to Integrate Testing a Controller, which inside that controller, methods gets token from another site
我正在设置一个 API,它通过 JWT 向另一台服务器进行身份验证。
我要测试的 Controller 方法之一是从外部站点获取令牌。
我该如何测试这个方法?
我制作了一个测试服务器并尝试模仿提供 tokens.i 可以通过测试方法访问此 Test Server
的网站操作,但我无法从实际控制器访问它。
这是我的测试服务器设置方法
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);
}
这是从 AuthController
调用的 AuthService 代码
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)访问它时,我无法访问它
您的代码与实现问题的耦合过于紧密,无法模拟组件以将其与第 3 方依赖项隔离开来。因为 HttpClient
是手动创建的,所以无法替换其处理程序来伪造请求。
考虑模拟注入被测控制器的身份验证服务本身。
For example
//...
var token = "{fake token here}";
var authService = Mock.Of<IAuthService>(_ =>
_.GetAuthenticationTokenAsync == Task.FromResult(token)
);
config.AddSingleton<IAuthService>(authService);
//...
我正在设置一个 API,它通过 JWT 向另一台服务器进行身份验证。 我要测试的 Controller 方法之一是从外部站点获取令牌。 我该如何测试这个方法?
我制作了一个测试服务器并尝试模仿提供 tokens.i 可以通过测试方法访问此 Test Server
的网站操作,但我无法从实际控制器访问它。
这是我的测试服务器设置方法
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);
}
这是从 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)访问它时,我无法访问它
您的代码与实现问题的耦合过于紧密,无法模拟组件以将其与第 3 方依赖项隔离开来。因为 HttpClient
是手动创建的,所以无法替换其处理程序来伪造请求。
考虑模拟注入被测控制器的身份验证服务本身。
For example
//...
var token = "{fake token here}";
var authService = Mock.Of<IAuthService>(_ =>
_.GetAuthenticationTokenAsync == Task.FromResult(token)
);
config.AddSingleton<IAuthService>(authService);
//...