Skip to content

TestAuthenticationStateProvider - make it easy to test components using authentication #146

@egil

Description

@egil

For components that use the authentication state provider directly or indirectly, there is a lot of boilerplate code to write to create a test, e.g. #135.

Like the MockJsRuntime in bUnit, a TestAuthenticationStateProvider could be provided that allows the user to choose and change the authentication state and user identification for a test.

E.g. something like this:

var authProvider = ctx.Services.AddTestAuthenticationStateProvider(); // defaults to unauthenticated
var authProvider = ctx.Services.AddTestAuthenticationStateProvider("egil"); // defaults to authenticated

Then to change the authenticated state, call:

authProvider.SetAuthenticated(string username);
authProvider.SetUnauthenticated();

@gulbanana has provided us with this sample implementation:

public sealed class TestAuthenticationStateProvider : AuthenticationStateProvider
{
	private string? _username;

	public TestAuthenticationStateProvider(string? username = null)
	{
		_username= username;
	}

	public override Task<AuthenticationState> GetAuthenticationStateAsync()
	{
		if (_username is null)
		{
			return Task.FromResult(new AuthenticationState(new ClaimsPrincipal()));
		}
		else
		{
			var nameClaim = new Claim(ClaimTypes.Name, _username);
			var identity = new ClaimsIdentity(new[] { nameClaim }, AuthenticationTypes.Basic);
			var principal = new ClaimsPrincipal(identity);

			return Task.FromResult(new AuthenticationState(principal));
		}
	}

	public void SetAuthenticated(string username)
	{
		_username = username;
		NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
	}

	public void SetUnauthenticated()
	{
		_username = null;
		NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
	}
}

Questions and TODO:

  • Does this cover all auth scenarios, e.g. both declarative in razor syntax and in c# code?
  • Are there other types of claims that should be supported besides just basic/username? Is it relevant for testing?
  • Test that we can correctly switch between authenticated and unauthenticated states.
  • Create unit tests that covers the TestAuthenticationStateProvider. This can most likely be a regular unit test, maybe with a single component test in the mix to verify that e.g. AuthorizeView is compatible.
  • Create a document page that describe how to use the TestAuthenticationStateProvider
  • Create a stub for TestAuthenticationStateProvider (Register stubs of all default services Blazor provides at runtime with useful helper message #115) the is registered by default and provides the user with a good error message that tells how to register TestAuthenticationStateProvider and link to docs. See example from JSMock at:
  • Code should probably be placed in src/bunit.web/TestDoubles/Auth or something similar.
  • Create an extension method for TestServiceProvider which supports registering with or without a username, e.g. Services.AddSingleton<TestAuthenticationStateProvider>().AddSingleton<AuthenticationStateProvider>(s => s.GetRequiredService<TestAuthenticationStateProvider>())

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions