#c# #unit-testing #mocking #moq
#c# #модульное тестирование #издевательство #moq
Вопрос:
Я тестирую метод OnPostAsync(), который занимается регистрацией нового пользователя. Когда тест выполняется с помощью метода, он встречает много переменных, и именно здесь у меня возникают проблемы, например, ссылка на объект не установлена для экземпляра объекта. Я получаю сообщение об ошибке в var user
, я уже CreateAsync()
издевался. Я опустил код для простоты Буду признателен за любую помощь!
Register.cshtml.cs
public class RegisterModel : PageModel
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;
public RegisterModel(
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
ILogger<RegisterModel> logger,
IEmailSender emailSender)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = "tester@gmail.com", Email = "tester@gmail.com" };
var result = await _userManager.CreateAsync(user, "falafelsrock");
if (result.Succeeded)
{
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
Console.WriteLine("Succeeded");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
}
}
RegisterModelTests.cs
[TestFixture]
public class RegisterModelTests
{
private Mock<FakeUserManager> _mockUserManager;
[SetUp]
public void SetUp()
{
_mockUserManager = new Mock<FakeUserManager>();
SetUpFakeUserManager();
}
public RegisterModel CreateRegisterModel()
{
return new RegisterModel(_mockUserManager.Object);
}
[Test]
[TestCase("tester@tester.co.uk")]
public async Task GivenValidInput_OnPostAsync_CreatesANewUser(string email)
{
// Arrange
var user = new IdentityUser { UserName = email, Email = email };
var unitUnderTest = CreateRegisterModel();
// Act
var result = await unitUnderTest.OnPostAsync("/asdsad/asda");
// Assert
if (result != null)
Assert.Pass();
}
private void SetUpFakeUserManager()
{
_mockUserManager.Setup(x => x.CreateAsync(It.IsAny<IdentityUser>(), It.IsAny<string>())
.ReturnsAsync(IdentityResult.Success);
}
}
Комментарии:
1. Что такое
Input.Email
? Другое дело, что user в setup и фактический код отличаются, поскольку они создаются с помощьюnew
ключевого слова. Это другой экземпляр…2. Ваш
Input
класс — это то, что известно как «окружающий контекст», что плохо, когда дело доходит до изоляции вашего кода для тестирования, поскольку он должен существовать, и если у него есть какая-либо функциональность, вы тестируете и это. Было бы лучше, если бы вы ввелиInput
класс sinch, который затем вы могли бы настроить в своем тесте.3. @Johnny Input — это просто свойство типа InputModel, InputModel просто содержит три строковых поля: имя, адрес электронной почты и пароль. Вот почему в моем тесте я просто использовал эти строки.
4. @HansKilian входной класс в этом экземпляре представляет всего три строки, поэтому я заменил их своими собственными жестко закодированными строками. Вы знаете, как я могу предотвратить возникновение ошибки? Это моя единственная забота прямо сейчас
5. @HansKilian большое спасибо за идею! Я кое-что прочитал и реализовал это сам, и, похоже, это работает. Я просто добавил InputModel в качестве временной службы , затем передал ее в конструктор и инициализировал. Похоже ли это на то, что вы бы сделали? 🙂