Skip to content

Instantly share code, notes, and snippets.

@Stayrony
Created March 15, 2019 16:27
Show Gist options
  • Save Stayrony/44311f5eec4cfa8d782de54f0e75e3e4 to your computer and use it in GitHub Desktop.
Save Stayrony/44311f5eec4cfa8d782de54f0e75e3e4 to your computer and use it in GitHub Desktop.
Unit testing ASP.NET Core Identity. Defines two fake classes: FakeUserManager and FakeSignInManager, which will be used by the mocking framework. Finally, we need to mock our FakeUserManager and FakeSignInManager classes by using Moq. The mocking will be implemented by the constructor (setup) of the InjectFixture class. And finally we can write …
[CollectionDefinition("Test")]
public class AccountServiceTests
{
private readonly InjectFixture _injectFixture;
public AccountServiceTests()
{
_injectFixture = new InjectFixture();
}
[Theory]
[InlineData("[email protected]", "Bred", "Apollo", 90)]
public async Task ConfirmEmail_ShouldThrowException_IfUserIdIsNullAsync(string email, string firstName,
string lastName, int passwordExpireInDays)
{
var user = new ApplicationUser()
{
Email = email,
FirstName = firstName,
LastName = lastName,
PasswordExpiredDate = _injectFixture.Generator.UtcNow().AddDays(passwordExpireInDays),
};
Task Act() => _injectFixture.AccountService.ConfirmEmailAsync(null, user.Email, "test");
await Assert.ThrowsAsync<ArgumentNullException>(Act);
Assert.Contains("userId", Act().Exception.Message);
}
[Theory]
[InlineData("[email protected]", "Bred", "Apollo", 90)]
public async Task ConfirmEmail_ShouldThrowException_IfCodeIsNullAsync(string email, string firstName,
string lastName, int passwordExpireInDays)
{
var user = new ApplicationUser()
{
Email = email,
FirstName = firstName,
LastName = lastName,
PasswordExpiredDate = _injectFixture.Generator.UtcNow().AddDays(passwordExpireInDays),
};
Task Act() => _injectFixture.AccountService.ConfirmEmailAsync(user.Id, user.Email, null);
await Assert.ThrowsAsync<ArgumentNullException>(Act);
Assert.Contains("code", Act().Exception.Message);
}
[Theory]
[InlineData("[email protected]", "Bred", "Apollo", 90, "wertyuiolkjmnbvcfdew3456789")]
public async Task ConfirmEmail_ShouldThrowException_IfUserIsNullAsync(string email, string firstName,
string lastName, int passwordExpireInDays, string code)
{
var user = new ApplicationUser()
{
Email = email,
FirstName = firstName,
LastName = lastName,
PasswordExpiredDate = _injectFixture.Generator.UtcNow().AddDays(passwordExpireInDays),
};
Task Act() => _injectFixture.AccountService.ConfirmEmailAsync(user.Id, user.Email, code);
await Assert.ThrowsAsync<ArgumentNullException>(Act);
Assert.Contains("user", Act().Exception.Message);
}
}
public class FakeSignInManager : SignInManager<ApplicationUser>
{
public FakeSignInManager()
: base(new Mock<FakeUserManager>().Object,
new HttpContextAccessor(),
new Mock<IUserClaimsPrincipalFactory<ApplicationUser>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<ILogger<SignInManager<ApplicationUser>>>().Object,
new Mock<IAuthenticationSchemeProvider>().Object)
{
}
}
public class FakeUserManager : UserManager<ApplicationUser>
{
public FakeUserManager()
: base(new Mock<IUserStore<ApplicationUser>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<ApplicationUser>>().Object,
new IUserValidator<ApplicationUser>[0],
new IPasswordValidator<ApplicationUser>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<ApplicationUser>>>().Object)
{
}
}
[CollectionDefinition("Test")]
public class FixtureCollection : ICollectionFixture<InjectFixture>
{
}
public class InjectFixture : IDisposable
{
public readonly UserManager<ApplicationUser> UserManager;
public readonly SignInManager<ApplicationUser> SignInManager;
public readonly IAccountService AccountService;
public readonly ApplicationDbContext DbContext;
public readonly IGenerator Generator;
public InjectFixture()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "FakeDatabase")
.Options;
DbContext = new ApplicationDbContext(options);
var users = new List<ApplicationUser>
{
new ApplicationUser
{
UserName = "Test",
Id = Guid.NewGuid().ToString(),
Email = "[email protected]"
}
}.AsQueryable();
var fakeUserManager = new Mock<FakeUserManager>();
fakeUserManager.Setup(x => x.Users)
.Returns(users);
fakeUserManager.Setup(x => x.DeleteAsync(It.IsAny<ApplicationUser>()))
.ReturnsAsync(IdentityResult.Success);
fakeUserManager.Setup(x => x.CreateAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>()))
.ReturnsAsync(IdentityResult.Success);
fakeUserManager.Setup(x => x.UpdateAsync(It.IsAny<ApplicationUser>()))
.ReturnsAsync(IdentityResult.Success);
fakeUserManager.Setup(x =>
x.ChangeEmailAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(IdentityResult.Success);
var signInManager = new Mock<FakeSignInManager>();
signInManager.Setup(
x => x.PasswordSignInAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>(), It.IsAny<bool>(),
It.IsAny<bool>()))
.ReturnsAsync(SignInResult.Success);
UserManager = fakeUserManager.Object;
SignInManager = signInManager.Object;
AccountService = new AccountService(UserManager);
Generator = new Generator();
}
public void Dispose()
{
UserManager?.Dispose();
DbContext?.Dispose();
}
}
@Stayrony
Copy link
Author

Stayrony commented Oct 2, 2020

I Try this example but don't works for me!
I am using .net core 2.2.
image

Hi!

You could see that the contract of SignInManager is changed, you need to create a fake implementation of IUserConfirmation.

@Nedaanasar
Copy link

Hi, What is the Interface IGenerator.
I get CS0246 The type or namespace name 'Generator' could not be found (are you missing a using directive or an assembly reference?

@Nedaanasar
Copy link

Hi, Have you tried to test create user and log in? can i have link to the source?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment