A utilização de métodos estáticos, na maioria dos casos, deve ser evitada por dificultar os testes unitários e criar um alto acoplamento. Mas se você se deparar com um método estático e tiver que sobrescrever seu comportamento para implementar testes unitários utilizando a técnica Mock Objects, indico a ferramenta PowerMock.
Esse framework permite a criação de mocks de métodos marcados com static ou até mesmo final. O PowerMock é utilizado como uma extensão de outras ferramentas de mock, como o EasyMock e o Mockito.
Exemplo
O trecho de código abaixo retirado deste exemplo, demonstra como utilizar o PowerMock com o EasyMock:
import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; import samples.singleton.StaticService; import static org.easymock.EasyMock.expect; import static org.junit.Assert.*; import static org.powermock.api.easymock.PowerMock.*; @RunWith(PowerMockRunner.class) @PrepareForTest( { StaticService.class }) public class MockStaticTest { @Test public void testMockStatic() throws Exception { mockStatic(StaticService.class); String expected = "Hello altered World"; expect(StaticService.say("hello")).andReturn("Hello altered World"); replay(StaticService.class); String actual = StaticService.say("hello"); verify(StaticService.class); assertEquals("Expected and actual did not match", expected, actual); } }
O método estático a ser “mockado” é o say da classe StaticService. Suponha que a implementação deste método retorna “Hello World”. O objetivo deste código de exemplo é sobrescrever o comportamento de say para retornar “Hello altered World” quando recebe “hello” como parâmetro.
A linha 12 define o runner do PowerMock para o JUnit 4 e a linha 13 informa quais as classes que devem ser preparadas para o teste. Entre as linhas 18 e 21 é definido o comportamento esperado para o metodo say, que é retornar “Hello altered World” quando receber “hello” como parâmetro. O método say é chamado na linha 23 e retornará o valor definido, o que é verificado nas linhas 25 e 26.
A utilização do PowerMock é praticamente igual à do EasyMock padrão, com excessão do runner, da annotation @PrepareForTest e da chamada do método mockStatic.
Por que eu preciso disso?
Um caso em que o PowerMock ajuda muito é quando foi utilizado o design pattern Singleton ou um Factory Method estático. Por exemplo, no código a seguir é chamado o método getInstance de ServicoAutenticacao.
public class LoginController { public void realizarLogin(String login, String senha) throws LoginInvalidoException { ServicoAutenticacao servicoAutenticacao = ServicoAutenticacao.getInstance(); //faz algo... } }
O problema é que para realizar os testes unitários você não deve utilizar a implementação real deste serviço, já que ele pode depender de recursos (banco de dados, LDAP, etc.) e é necessário sobrescrever seu comportamento para os testes. Com o PowerMock você sobrescreve o método estático para retornar uma implementação fake do serviço ou um mock object.
O ideal neste caso seria substituir o método estático por uma Injeção de Dependência, porém isso não é possível se você estiver utilizando uma API ou framework que tenha uma chamada desse tipo.
Instalação
A página Getting Started da wiki do projeto explica como adicionar a biblioteca em seu projeto, utilizando o Maven ou não.
Últimos comentários