Basically, I would like to do a clean Integration Testing using net6.0. I want to invoke the endpoints of my controller which will eventually go into the database and write some data. Afterward, I will assert some aspects of the inserted data.
I can bypass the Bearer Token used by [Authorize] attribute but cannot bypass my custom attribute named as [HasPermission]
I have this custom attribute:
public class HasPermission : TypeFilterAttribute
{
public HasPermission(string resource, string scope)
: base(typeof(HasPermissionAuthorize))
{
Arguments = new object[] { resource, scope };
}
};
public class HasPermissionAuthorize : IAuthorizationFilter
{
private readonly string _resource;
private readonly string _scope;
private readonly IAuthService _authService;
public HasPermissionAuthorize(string resource, string scope, IAuthService authService)
{
_resource = resource;
_scope = scope;
_authService = authService;
}
public async void OnAuthorization(AuthorizationFilterContext context)
{
string token = context.HttpContext.Request.Headers["Authorization"];
token = token.Replace("Bearer ", "");
bool hasPermission = await _authService.HasClaimAsync(token, "permission", _resource "." _scope);
if (!hasPermission)
{
context.Result = new UnauthorizedResult();
}
}
And this is my controller:
[Authorize] //<-- I can bypass this
[Route("v1/[controller]")]
[ApiController]
public class MachinesController : ControllerBase
{
[HasPermission("Machines", "Create")] //<-- How do I bypass this?
[HttpPost]
public async Task<IActionResult> Post([FromBody] AddMachineRequest request)
{
//some logic
}
}
In my Integration Testing
public class ApiWebApplicationFactory : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
//I'm bypassing the [Authorize] attribute here
//However, I do not know how to bypass [HasPermission] attribute
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes("Test")
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Test";
options.DefaultChallengeScheme = "Test";
options.DefaultScheme = "Test";
}) //TestAuthHandler is written somewhere else
.AddScheme<AuthenticationSchemeOptions, TestAuthHandler>("Test", options => { });
}
}
}
I'm testing my code using IClassFixture<ApiWebApplicationFactory>. Even though I can bypass [Authorize] attribute, I could NOT find an elegant way to bypass [HasPermission] attribute.
CodePudding user response:
OK. I already was thinking about Mocking IAuthService but as also Guru Stron pointed out, I went for that approach. So, here is my latest update on the code that solves my problem:
public class ApiWebApplicationFactory : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
//Added this line
services.AddTransient<IAuthService>(_ => _authServiceMock.Object);
//Above somewhere I also mocked it like this:
//_authServiceMock.Setup(c => c.HasClaimAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
//other stuff from my original question remains here and they are the same
}
}
}
