Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a class with a method that returns an object of type 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 is a domain object. Note the Id property with setter as protected:

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 is protected because it is generated by the database.

Test project

In my Test project I have a Fake repository with a method Store to save/update the object:

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);
    }
}

In CustomMembershipProvider I have public override MembershipUser CreateUser method that calls the GetUser to create a User.
This way, all I have to do is mock the GetUser method so that the repository can generate the 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;

Problem

In theory everything is correct. When CreateUser call 'GetUser' to create a user, the user will return Mock filled;

[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);
}

The problem is that Email, Name, Password are empty (with default values)!

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
163 views
Welcome To Ask or Share your Answers For Others

1 Answer

The way you prepare the mocked user is the problem.

moqUser.Object.Name = username;

will not set the name, unless you have setup the mock properly. Try this before assigning values to properties:

moqUser.SetupAllProperties();

This method will prepare all properties on the mock to be able to record the assigned value, and replay it later (i.e. to act as real property).

You can also use SetupProperty() method to set up individual properties to be able to record the passed in value.

Another approach is:

var mockUser = Mock.Of<User>( m =>
    m.Name == "whatever" &&
    m.Email == "someone@example.com"); 

return mockUser;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...