Utilizando abstrações de métodos estáticos em testes


Vi um exemplo em um curso de TDD de como mockar objetos no testes, afim de focar no código a ser testado, e não em objetos de infraestrutura. Já utilizei Mockito e EasyMock. Mas para alguns cenários, uma abstração resolve o problema.

Vamos imaginar o seguinte cenário: uma classe com método salvar que utiliza um método estático com alguma dependência com o contexto web, por exemplo.

Classe utilitária com método estático

public class WebUtil {
    public static void showSuccessfulMessage() {
        //some crazy web dependency here
    }
}

Classe a ser testada

public class UserController {
    public String save() {
        //some crazy repository methods here
        WebUtil.showSuccessfulMessage();
        return “”;
    }
}

Ao criar um teste para o método save, esbarramos em um problema: dificuldade para se mockar métodos estáticos (nem toda api tem essa opção). E mesmo que seja feito o mock, seria interessante obtermos algumas informações para os asserts. A sugestão então seria encapsular o método estático em uma classe, e daí sim, extendê-la e sobrescrever o método que usa a chamada estática. Ficaria assim:

Nova classe encapsuladora

public class Helper {
    public void showSuccessfulMessage() {
        WebUtil.showSuccessfulMessage();
    }
}

Nova utilização na classe a ser testada

public class UserController {
    private Helper helper;
    public UserController(Helper helper) {
        this.helper = helper;
    }
    public String save() {
        //some crazy repository methods here
        helper.showSuccessfulMessage();
        return “”;
    }
}

Classe abstrata de Helper, com mais informações que serão usadas durante o teste

public class HelperTest extends Helper {
    private int qtyMessages;
    public int getQtyMessages() {
        return qtyMessages;
    }
    public void showSuccessfulMessage() {
        System.out.println(“overriding method”);
        qtyMessages++;
    }
}

E finalmente, a classe de teste:

public class UserBeanTest {
    @Test
    public void saveWithSuccess() {
        HelperTest helper = new HelperTest();
        UserBean bean = new UserBean(helper);
        bean.save();

        Assert.assertEquals(1, helper.getQtyMessages());
    }
}

Pronto, dessa forma, conseguimos controlar outras informações que sejam interessantes no teste (qtyMessages) e que não existem na classe original. Além disso, diminuimos a dependência de ambiente não disponíveis no momento do teste, como contexto web.

Like what you read? Give Owls are birds a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.