Как создать макет переменной, которая инициализируется новым объектом

#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 в качестве временной службы , затем передал ее в конструктор и инициализировал. Похоже ли это на то, что вы бы сделали? 🙂