Я пытаюсь выполнить модульное тестирование моего ASP.NET Core WebAPI с проектом XUnit. Я использую 3-х уровневую архитектуру, где каждый слой находится в своем проекте библиотеки классов, а зависимости решаются с помощью внедрения зависимостей. Все работает нормально. Но когда я хочу выполнить модульное тестирование, я застрял с насмешками над уровнем логики и уровнем данных. Когда я запускаю тест, я получаю эту ошибку:
Сообщение: System.ArgumentException: аргументы конструктора не могут быть переданы для макетов интерфейса.
Мой Mock Object генерируется в этом классе:
public static class MockObjects
{
public static Mock<UserManager<TUser>> GetUserManagerMock<TUser>() where TUser : IdentityUser
{
return new Mock<UserManager<TUser>>(
new Mock<IUserStore<TUser>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<TUser>>().Object,
new IUserValidator<TUser>[0],
new IPasswordValidator<TUser>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<TUser>>>().Object);
}
public static Mock<SignInManager<TUser>> GetSignInManagerMock<TUser>() where TUser : IdentityUser
{
return new Mock<SignInManager<TUser>>(
GetUserManagerMock<TUser>().Object,
new Mock<IHttpContextAccessor>().Object,
new Mock<IUserClaimsPrincipalFactory<TUser>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<ILogger<SignInManager<TUser>>>().Object,
new Mock<IAuthenticationSchemeProvider>().Object
);
}
public static Mock<RoleManager<TIdentityRole>> GetRoleManagerMock<TIdentityRole>() where TIdentityRole : IdentityRole
{
return new Mock<RoleManager<TIdentityRole>>(
new Mock<IRoleStore<TIdentityRole>>().Object,
new IRoleValidator<TIdentityRole>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<ILogger<RoleManager<TIdentityRole>>>().Object);
}
public static Mock<ApplicationDbContext> GetDbContextMock()
{
return new Mock<ApplicationDbContext>(new DbContextOptions<ApplicationDbContext>());
}
public static Mock<TRepository> GetRepositoryMock<TRepository>() where TRepository : class
{
return new Mock<TRepository>(GetDbContextMock().Object);
}
public static Mock<ISmsService> GetSmsServiceMock()
{
return new Mock<ISmsService>(GetRepositoryMock<SmsRepository>().Object);
}
public static Mock<IEmailService> GetEmailServiceMock()
{
return new Mock<IEmailService>(GetRepositoryMock<EmailRepository>().Object);
}
public static Mock<IProfileService> GetProfileServiceMock()
{
return new Mock<IProfileService>(GetRepositoryMock<ProfileRepository>().Object);
}
public static Mock<IAccountService> GetAccountServiceMock()
{
return new Mock<IAccountService>(
GetUserManagerMock<ApplicationUser>().Object,
GetSignInManagerMock<ApplicationUser>().Object,
GetSmsServiceMock().Object,
GetEmailServiceMock().Object,
new Mock<IConfiguration>().Object,
GetProfileServiceMock().Object
);
}
}
Я реализовал этот класс после этой записи в блоге: https://dejanstojanovic.net/aspnet/2019/september/unit-testing-repositories-in-aspnet-core-with-xunit-and-moq/
Мой метод тестирования:
[Fact]
public async Task RegisterSimpleTest()
{
// Arrange
var mockService = MockObjects.GetAccountServiceMock().Object;
var controller = new AccountController(mockService);
var data = new EmailRegisterViewModel()
{
Email = "a@a.a",
Password = "123456",
ConfirmPassword = "123456"
};
// Act
var result = await controller.Register(data) as ObjectResult;
// Assert
Assert.NotNull(result);
Assert.Equal(200, result.StatusCode);
}
И действие контроллера, которое я хочу проверить:
[HttpPost]
public async Task<IActionResult> Register([FromBody]EmailRegisterViewModel model)
{
if (!ModelState.IsValid)
{
var errors = ModelStateExtention.GetModelErrors(ModelState);
return BadRequest(errors);
}
var user = new ApplicationUser()
{
UserName = model.Email,
Email = model.Email
};
var result = await _accountService.EmailRegisterAsync(user, model.Password);
return StatusResultExtension<ActionMessage>.GetStatusResult(result);
}
Как выполнить модульный тест? Что я не так делаю?