Como os objetos simulados são comumente mal utilizados?

15

Li recentemente um artigo que dizia que objetos simulados geralmente são mal compreendidos e mal utilizados. Existem claros anti-padrões zombeteiros que eu posso observar?

Armand
fonte
é o artigo que você leu este? martinfowler.com/articles/mocksArentStubs.html
keppla
não ... não me lembro a fonte exata, mas vou postar aqui se eu fizer
Armand
Fui encarregado da tarefa no stackoverflow por zombar da API do mongodb. Fui apontado para uma postagem de blog que alegava que é errado zombar de qualquer classe que você não tenha escrito. Na verdade, eu discordo disso, mas a opinião está lá fora.
Kevin

Respostas:

13

Eu odeio ver simples classes concretas ridicularizadas. Por exemplo, considere a seguinte classe simples, que não depende de mais nada:

public class Person
{
    private readonly string _firstName;
    private readonly string _surname;

    public Person(string firstName, string surname)
    {
        if (String.IsNullOrEmpty(firstName))
        {
            throw new ArgumentException("Must have first name");
        }

        if (String.IsNullOrEmpty(surname))
        {
            throw new ArgumentException("Must have a surname");
        }

        _firstName = firstName;
        _surname = surname;
    }

    public string Name 
    {
        get
        {
            return _firstName + " " + _surname;
        }
    }
}

Em todos os testes que envolvem essa classe, eu prefiro que um real seja instanciado e usado, em vez de alguma interface como 'IPerson' sendo retirada, uma zombada usada e expectativas definidas no. Ao usar o real, seu teste é mais realista (você tem as verificações de parâmetros em vigor e a implementação real da propriedade 'Nome'). Para uma classe simples como essa, você não está tornando seus testes mais lentos, menos determinísticos ou atrapalhando a lógica (não é provável que você precise saber que Nome foi chamado ao testar alguma outra classe) - que são os motivos habituais para zombar / stubbing.

Como uma extensão disso, também vi pessoas escreverem testes nos quais o mock é configurado com uma expectativa, e o mock é chamado diretamente no teste. Sem surpresa, o teste sempre passa ... hmmmm ...

FinnNk
fonte
Felizmente, zombando de estruturas que eu usei foram capazes de zombar de classes concretas; portanto, retirar interfaces em pontos inconvenientes não é um problema.
Armand
5
Isso não muda o problema - esse tipo de coisa simples geralmente não deve ser ridicularizado, mesmo se você estiver usando algo que relaxe as restrições técnicas sobre o que pode ser ridicularizado (por exemplo, uma estrutura falsa como o TypeMock ou uma linguagem dinâmica).
FinnNk
Minha regra geral sempre foi zombar de comportamento, não de dados.
Ardave # 15/13
10

Pode parecer óbvio, mas: Não use objetos simulados no código de produção! Eu já vi mais de um exemplo em que o código de produção dependia das características de certos objetos simulados ( MockHttpServletRequestdo Springframework, por exemplo).

perdian
fonte
14
Espero que você tenha seguido seu dever sagrado e tenha enviado o código ao DailyWTF?
keppla
1
No meu trabalho anterior, fomos expressamente proibidos de enviar qualquer coisa da nossa base de código para o DWTF.
10136 quantidev
9
@quant_dev: O fato de que eles tinham essa política um implica coisas assustadoras sobre seus desenvolvedores ...
John Fisher
1
Na verdade não. Era uma startup que precisava desenvolver rapidamente uma base de código para vender um produto e, em seguida, começou a consolidá-la e refatorá-la para quitar a dívida técnica, à medida que o produto amadurecia e o desenvolvimento adicional era dificultado pelo (falta de) design inicial. Os gerentes sabiam que a antiga base de código era uma merda e investiram tempo e recursos na refatoração, mas não queriam arriscar nenhuma publicidade adversa.
quant_dev 11/06/11
Basta tomar atalhos não é realmente suficiente para obter só dailywtf ...
poolieby
9

Na minha opinião, é a verificação de invocação excessiva de método em zombarias. Eu sinto que essa é uma prática imposta por algumas estruturas de simulação, como o EasyMock, onde o comportamento padrão de simulação é falhar sempre que houver uma chamada de método adicional que não era exatamente especificada anteriormente. Esse tipo de verificação estrita do método simulado pode levar a projetos frágeis, nos quais a menor alteração no código pode levar a um conjunto de testes falhando, mesmo que a funcionalidade principal ainda seja a mesma.

Uma solução para isso está começando a usar stubs em vez de zombarias. Um artigo que achei particularmente esclarecedor sobre o assunto foi encontrado no Javadoc de Mockito: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html (consulte "2. Que tal uma punhalada?" ), com link para: http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/ .

Até agora, gostei de trabalhar com o Mockito, porque ele não impõe esse comportamento estrito de zombaria, mas o uso de stubs. Também impõe a verificação de métodos específicos, em vez de todo o objeto simulado; então você acaba verificando apenas os métodos que realmente importam no seu cenário de teste.

Existem alguns livros aqui e ali, posso recomendar que abordem esse assunto e que sejam zombeteiros e gerais:

Padrões xUnit

A arte do teste de unidade: com exemplos em .Net

Teste Java de próxima geração: TestNG e conceitos avançados (este livro é principalmente sobre testNG, mas há um bom capítulo sobre zombaria)

Fabio Kenji
fonte
+1 para o ponto em verificações excessivas de chamada de método. No entanto, sempre há o outro lado da moeda em que uma invocação inesperada de método causa uma falha no seu método. Felizmente, o Mockito tem a Answer.RETURNS_SMART_NULLSconfiguração para zombarias, o que ajuda a diagnosticar isso.
precisa saber é o seguinte
4

Eu observei poucos anti-padrões em minha experiência.

  • Classes de domínio sendo ridicularizadas / stub em que uma mudança de estado pode ocorrer e que precisa ser verificada.
  • Testes de integração interagindo com uma mistura de zombarias e classes concretas que anulam o objetivo dos testes de integração.
  • Uso inadvertido de zombarias no código de produção (isso nunca deve acontecer)

Caso contrário, minha experiência com zombarias, especialmente Mockito, foi fácil. Eles tornaram os testes muito fáceis de escrever e manter. O teste de interação do modo de exibição / apresentador do GWT é muito mais fácil com as simulações do que o GWTTestCase.

Vinod R
fonte
2 e 3 são problemas definitivos! Você tem um exemplo simples de (1)?
Armand
2

Acho que os testes que utilizam simulações em várias camadas de um aplicativo são particularmente difíceis de decifrar e alterar. No entanto, acho que isso foi atenuado nos últimos anos por APIs de frameworks simuladas aprimoradas (eu uso o JMock quando conveniente).

Há 5 ou 6 anos, APIs como o EasyMock eram poderosas, mas muito pesadas. Frequentemente, o código de teste que o utilizava era ordens de magnitude mais complicadas do que o código que estava testando. Naquela época, eu tentei influenciar as equipes em que eu estava para usá-lo com moderação e se contentar com zombarias artesanais simples que eram simplesmente implementações alternativas de interfaces especificamente para testes.

Recentemente, minhas opiniões fortes sobre isso se tornaram mais suaves, pois as APIs de zombaria tornaram os testes que os utilizam mais legíveis. Essencialmente, quero que meu código (incluindo testes) seja alterável por outros desenvolvedores sem fazê-los sentir como se estivessem analisando um atoleiro de chamadas obscuras de API.

rupjones
fonte