Validacao de objeto mock

5 respostas
C

Alguem conhece uma forma mais simples de assegurar que o metodo de um objeto mock seja chamado corretamente?

Queria saber se existe alguma forma mais direta, que nao necessite criar custom matchers como esse:

@Ignore("This is a custom matcher, not a test!")
public class FixMatcher extends TypeSafeMatcher<Fix> {
    ...

    @Factory
    public static Matcher<Fix> aFixSuch(Fix fix) {
        return new FixMatcher(fix);
    }
   
    @Override
    public boolean matchesSafely(Fix item) {
        return fix.getOwner() == item.getOwner() &&
                fix.getLatitude() == item.getLatitude() &&
                    fix.getLongitude() == item.getLongitude();
    }

    ...
}

O metodo matchesSafely() acima verifica se o mock geoFixer.save(fix) foi chamado corretamente:

@Test
public void shouldSaveAFix() {
    final double lat = 23.32;
    final double lon = 43.43;

    context.checking(new Expectations() {
        {
            Fix fix = new Fix(account.getId(), lat, lon);

            one(geoFixer).save(with(aFixSuch(fix)));
        }
    });
       
    account.fix(lat, lon);
}

É normal criar custom matchers para esses casos ou existe uma solucao melhor?

5 Respostas

Lucas_Cavalcanti

dá uma olhada, e vê se isso te ajuda:

C

Baseado no exemplo do seu artigo…

Supondo que fosse LucasLoginLogic e o objeto User fosse criado internamente:

public class LucasLoginLogic { ... public void login() { User user = new User("lucas", "123", false, true); ... } }
Não bastaria esperar qualquer user: one(session).setAttribute(“user”, with(any(User.class)));

Como garantir que o objeto passado fosse User(“lucas”, “123”, false, true)?

Lucas_Cavalcanti

se o seu método equals() foi sobrescrito corretamente, você pode fazer o seguinte:

final User user = new User("lucas", "123", false, true);
mockery.checking(new Expectations() {{
    one(session).setAttribute("user", user);
}});

o teste só vai passar se o usuário passado pra sessão for equals() ao user que vc passou.

C

lucascs:
se o seu método equals() foi sobrescrito corretamente, você pode fazer o seguinte:

final User user = new User("lucas", "123", false, true);
mockery.checking(new Expectations() {{
    one(session).setAttribute("user", user);
}});

o teste só vai passar se o usuário passado pra sessão for equals() ao user que vc passou.

Acontece que User é uma entidade do meu dominio e portanto equals não se aplica aos seus valores mas ao id do usuario, como o objeto User no meu caso nem foi salvo no repositorio ainda ele sera sempre false na comparacao com qualquer outro objeto User (seu id é 0).

Sem querer ser chato, apenas buscando uma solucao melhor :slight_smile:

editado: e criar um metodo no objeto para fazer essa comparacao nao acho muito adequado por ser uma exigencia de teste afetando um objeto do meu sistema.

Lucas_Cavalcanti

então… acontece que geralmente vc não vai instanciar o User direto dentro da sua classe
(vc estiver fazendo isso significa que sua lógica está com alto acoplamento)…

ou seja… ao inves de instanciar o user, vc passa ele como parâmetro da lógica:

logica.login(user);

daí vc pode passar um user com o id setado, e vai dar true no método equals…

e se sua lógica acessa o banco de dados, mocka o banco de dados também (de novo vc tem que receber
o objeto do banco - Dao ou whatever - por injeção de dependência…

o ponto é que as suas classes às vezes tem que ser modificadas para serem testadas… injeção de dependência
e inversão de controle se aplicam a esse caso, e é sempre bom fazer isso…

[]'s

Criado 16 de março de 2008
Ultima resposta 18 de mar. de 2008
Respostas 5
Participantes 2