Mock da forma correta

54 views
Skip to first unread message

Riderman Sousa

unread,
May 29, 2013, 2:02:36 PM5/29/13
to dotnetar...@googlegroups.com

Estava com um problema com Moq sobre como setar propriedades e até cheguei a posta uma dúvida no Stackoverflow que levantou outra dúvida de Designer.

E para esta dúvida de designer gostaria de saber a opinião de vocês.

Problema

Minha app possui um CustomMembershipProvider e no método CreateUser um objeto de domínio é criado:

public class CustomMembershipProvider : MembershipProvider
{
    public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
    {
        // ..

        var user = GetUser(username, password, email, isApproved); // 

        UserRepository.Store(user);
        status = (user.Id > 0 ? MembershipCreateStatus.Success : MembershipCreateStatus.UserRejected);

        // ...
    }

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

Porém meu objeto de domínio possui a pripriedade Id como 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 é gerado pelo banco de dados

Então criei um teste:

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

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

Problema

O que ocorre é que no projeto de testes, um repositório Fake é utilizado. Então o Id não será gerado!
Preciso de uma forma de gerar o Id! Mais do que isso preciso de uma forma de settar o Id.

Solução encontrada

Pesquisando na internet, uma solução encontrada foi mocar o objeto User. Porém para mocar o objeto User teria de mocar minha classe CustomMembershipProvider, então mocar o método GetUser para retornar um Mock<User> e só então ser capaz de setar o Id. :)

var membershipMoq = new Mock<CreditoImobiliarioMembershipProvider>();
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.SetupProperty(p => p.Name, username);
        moqUser.SetupProperty(p => p.Password, password);
        moqUser.SetupProperty(p => p.Email, email);
        moqUser.SetupProperty(p => p.Status, isAproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente);
        return moqUser.Object;
    });

Pergunta

Além de uma quebra de designer, acredito que esta abordagem possa trazer vários problemas!

Um deles é o password é encriptado, o que ocorre quando moco o método GetUser é que o password não é mais encriptado! Mesmo porque o método para criptografar o password também é protected.


Atenciosamente,

Riderman de Sousa Barbosa

Web Developer | MCPD Certify

Skype.: 4042-6002 | Cel.: (31) 8681-1986

bindsolution.com

Microsoft Parner Network



Marcelo Oliveira

unread,
May 31, 2013, 10:19:37 PM5/31/13
to dotnetar...@googlegroups.com
Normalmente nesse teste em especifico você verifica se o repositorio foi chamado com os parâmetros corretos e ponto final...

Alguma razão pra usar um repositório fake nesse teste? 
Pra testar se o 'status' está sendo setado corretamente você teria que criar pelo menos 3 testes diferentes:
1) stubando o repositorio pra retornar um user com id 0
2) stubando o repositorio pra retornar um user com id diferente de 0
3) stubando o repositorio jogando uma exceção 

Existem outros detalhes da implementação que não me agradam...
Tens como criar um gist publico com o código da classe e do teste?


Marcelo Oliveira


2013/5/29 Riderman Sousa <rider...@bindsolution.com>

--
Você recebeu esta mensagem porque faz parte do grupo .Net Architects hospedado no Google Groups.
Para postar envie uma mensagem para dotnetar...@googlegroups.com
Para sair do grupo envie uma mensagem para dotnetarchitec...@googlegroups.com
Para mais opções visite o grupo em http://groups.google.com/group/dotnetarchitects?hl=pt-br
---
Você está recebendo esta mensagem porque se inscreveu no grupo ".Net Architects" dos Grupos do Google.
Para cancelar a inscrição neste grupo e parar de receber seus e-mails, envie um e-mail para dotnetarchitec...@googlegroups.com.
Para obter mais opções, acesse https://groups.google.com/groups/opt_out.
 
 

Reply all
Reply to author
Forward
0 new messages