Подтвердить что ты не робот

Как назначить значения свойствам в moq?

У меня есть класс с методом, который возвращает объект типа User

public class CustomMembershipProvider : MembershipProvider
{
    public virtual User GetUser(string username, string password, string email, bool isApproved)
    {
        return new User()
            {
                Name = username
                ,Password = EncodePassword(password)
                ,Email = email
                ,Status = (isApproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente)
                // ...
            };
    }

    // ..
}

User - объект домена. Обратите внимание на свойство Id с установщиком как защищенным:

public class User : IAuditable, IUser
{
    public virtual int Id { get; protected set; }
    public virtual string Name { get; set; }
    public virtual string Email { get; set; }
    public virtual UsuarioStatusEnum Status { get; set; }
    public virtual string Password { get; set; }
}

Id защищен, потому что он создается базой данных.

Проект тестирования

В моем тестовом проекте у меня есть поддельный репозиторий с методом Store для сохранения/обновления объекта:

public void Store(T obj)
{
    if (obj.Id > 0)
        _context[obj.Id] = obj;
    else
    {
        var generateId =  _context.Values.Any() ? _context.Values.Max(p => p.Id) + 1 : 1;
        var stubUser = Mock.Get<T>(obj); // In test, will always mock
        stubUser.Setup(s => s.Id).Returns(generateId);
        _context.Add(generateId, stubUser.Object);
    }
}

В CustomMembershipProvider У меня есть метод public override MembershipUser CreateUser, который вызывает GetUser для создания User.
Таким образом, все, что мне нужно сделать, - это mock метод GetUser, чтобы репозиторий мог генерировать Id

var membershipMoq = new Mock<CustomMembershipProvider>();
membershipMoq.CallBase = true;
membershipMoq
    .Setup(p => p.GetUser(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
    .Returns<string, string, string, bool>( (username, password, email, isAproved) => {
        var moqUser = new Mock<User>();
        moqUser.Object.Name = username;
        moqUser.Object.Password = password;
        moqUser.Object.Email = email;
        moqUser.Object.Status = (isAproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente);
        return moqUser.Object;
    });
_membershipProvider = membershipMoq.Object;

Проблема

В теории все правильно. Когда CreateUser вызывает "GetUser" для создания пользователя, пользователь вернет заполненный макет;

[TestMethod]
public void CreateUser_deve_criar_usuario_no_repositorio()
{
    // Act
    MembershipCreateStatus status;
    var  usr = _membershipProvider.CreateUser(
        _fixture.Create<string>(),
        _fixture.Create<string>(),
        _fixture.Create<string>(),
        null, null, true, null,
        out status);

    // usr should have name, email password filled. But not!

    // Assert
    status.Should().Be(MembershipCreateStatus.Success);
}

Проблема в том, что электронная почта, имя, пароль пустые (со значениями по умолчанию)!

enter image description here

4b9b3361

Ответ 1

Проблема в том, как вы готовите издеваемого пользователя.

moqUser.Object.Name = username;

не будет устанавливать имя, если вы не правильно настроили макет. Попробуйте это, прежде чем присваивать значения свойствам:

moqUser.SetupAllProperties();

Этот метод подготовит все свойства на макете, чтобы иметь возможность записать назначенное значение, и воспроизвести его позже (т.е. действовать как реальное свойство).

Вы также можете использовать метод SetupProperty(), чтобы настроить отдельные свойства, чтобы иметь возможность записать переданное значение.

Другой подход:

var mockUser = Mock.Of<User>( m =>
    m.Name == "whatever" &&
    m.Email == "[email protected]"); 

return mockUser;

Ответ 2

Я думаю, что вам не хватает насмешки. Маки, используемые для издевательства зависимостей класса, который вы тестируете:

enter image description here

Проверяемая система (SUT) должна тестироваться изолированно (то есть отдельно от других устройств). В противном случае ошибки в зависимостях приведут к сбою теста SUT. Также вы не должны писать тесты для mocks. Это ничего не дает, потому что издевательства не являются производственным кодом. Mocks не выполняется в вашем приложении.

Итак, вы должны высмеивать CustomMembershipProvider только в том случае, если вы тестируете некоторую единицу, которая зависит от нее (BTW лучше создать некоторую абстракцию, такую ​​как интерфейс ICustomMembershipProvider).

Или, если вы пишете тесты для класса CustomMembershipProvider, тогда его не следует издеваться - только зависимости этого провайдера должны быть издевались.