SlideShare uma empresa Scribd logo
1 de 31
Teste
Estilo de desenvolvimento guiado pela criação
de testes que validam a funcionalidade
implementada antes da criação do código de
produção
◦ Código mais simples
◦ Algoritmos confiáveis
◦ Menor custo de manutenção
Aumento de complexidade em cenários de
testes funcionais (interface de usuários,
repositórios)
Apoio gerencial
Testes falhos causam programas falhos
Testes de cobertura
Lacunas de testes
Falso senso de segurança (TDD não é bala de
prata)
Testes requerem visibilidade dos métodos
Encapsulamento requer esconder métodos
Use nomes de pacotes iguais
◦ Classe de produção está no pacote com.foo.bar
◦ Classe de teste deve ficar no pacote com.foo.bar
Use modificadores protected
e package (default)
Testes requerem comportamento específicos
Testes requerem objetos controláveis
Testes requerem Mocks
Frameworks de Mocks
◦ Mockito
◦ EasyMock
◦ PowerMock
Framework de Mock
◦ Simples
◦ Claro
◦ Intuitivo (depois que você entende sua lógica)
◦ Versão atual 1.9.0
◦ Documentação e notícias
http://code.google.com/p/mockito/
@Test
public void myTest() {
SomeObject myMock = Mockito.mock(SomeObject.class);
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations =
{"/applicationContext.xml"})
public class SourceCheckerTest {
@Autowired
SourceChecker sourceChecker;
@Mock
SourceRepository mockRepository;
@Before
public void before() {
MockitoAnnotations.initMocks(this);
}
Adiciona um comportamento a um dado
método de um mock
public SourceVO getSource(RequestVO request) {
SourceVO sourceVO = null;
sourceVO = repository.loadById(request.getSourceId());
…
}
@Test
public void procuraSourceExistenteTest() throws RepositoryException {
SourceVO sourceVO = getSourceVO();
String sourceId = sourceVO.getId().toString();
Mockito.when(mockRepository.loadById(sourceId)).thenReturn(sourceVO);
RequestVO request = Given.request();
request.setSourceId(sourceId);
SourceVO source = sourceChecker.getSource(request);
…
}
//Retorna dado valor
Mockito.when(mockRepository.loadById(sourceId)).thenReturn(sourceVO);
//Retorna exceção
Mockito.when(mockRepository.loadById(sourceId)).thenThrow(new NullPointerException());
//Chama o método real
Mockito.when(mockRepository.loadById(sourceId)).thenCallRealMethod();
//Cria uma resposta customizada
Mockito.when(mockRepository.loadById(sourceId)).thenAnswer(…);
//Retorna dado valor
Mockito.when(counter.getId()).thenReturn(1).thenReturn(2).thenReturn(3). thenThrow(new
NullPointerException());
É possível programar ações consecutivas para
um dado método. Muito útil quando se quer
ações diferentes a cada chamada de método.
Ex.: Loop
Mock é feito com a comparação de objetos,
muitas vezes não temos o objeto exato para
se comparar
Mockito.when(lotteryMock.theChosenOne(Mockito.anyMap())).thenReturn(categId);
Mockito.any();
Mockito.any(CampaignVO.class);
Mockito.anyBoolean();
Mockito.anyInt();
Mockito.anyCollection();
Mockito.anyCollectionOf(String.class);
Mockito.anyList();
Mockito.anyListOf(Integer.class);
Mockito.anyVararg();
Matchers customizados também podem ser
criados mas a sua utilização é muito rara
Métodos void são um caso a parte para o
Mockito pois o when recebe o método a ser
mockado como parâmetro e o compilador
java não aceita isso
public static void main(String[] args) {
System.out.println(getNum()); //OK
System.out.println(getVoid()); // ERROR
}
private static Integer getNum() {
return 5;
}
private static void getVoid() { }
Uso dos métodos doThrow e
doCallRealMethod
Mockito.doThrow(NullPointerException.class).when(sourceRepository).loadById("123456");
Mockito.doCallRealMethod().when(sourceRepository).loadById("123456");
Os mocks conseguem retornar objetos
controlados mas as vezes deseja-se
interceptar a chamada para alterar a resposta,
verificar os parâmetros passados e executar
ou não o método real para isso existe o
Answer
Evite usar answer, procure soluções mais
simples.
Dentro do AdServer o Answer foi usado para
validar a passagem de argumentos em
métodos complexos
public void makeSearch(CampaignVO campaign) {
changeCampaignName(campaign);
changeOtherValue(campaign);
repository.search(campaign); // What are the campaign's attributes?
}
Ex.: Desejo validar a campanha passada no repositório já que
essa campanha pode ter sido alterada por métodos
intermediários
Mockito.doAnswer(new Answer<Map<Long, Double>>() {
public Map<Long, Double> answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
// valida país recebido
List<AdVO> adVO = (List<AdVO>) args[0];
Assert.assertTrue(adVO.size() == 1);
Assert.assertEquals("728_90", adVO.get(0).getDimension());
return values;
}
}).when(adSelectorSpy).createAdsValues(adList);
Valido se o primeiro argumento passado possui um elemento
e se esse elemento tem um valor específico
O que acontece se você deseja controlar
apenas uma parte de um objeto?
◦ Ex.: Deseja-se testar um método que chama outro
método dentro da mesma classe
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations =
{"/applicationContext.xml"})
public class SourceCheckerTest {
@Autowired
SourceChecker sourceChecker;
SourceChecker checkerSpy;
@Before
public void before() {
checkerSpy = Mockito.spy(sourceChecker);
}
Espiamos o comportamento
de um método real
Um pouco de teoria
◦ Quando um método é mockado ele é executado, porém
como ele não existe, não há problema
◦ Mockar um método de um objeto espionado faz o método
ser executado, porém como ele é real isso pode causar
problemas
◦ Spies devem usar métodos doThrow, doReturn e doNothing
◦ MOCKS NUNCA executam métodos reais até que digamos o
contrário (thenCallRealMethod ou doCallRealMethod), SPIES
SEMPRE executam métodos reais até que digamos o
contrário (doNothing)
@Autowired
TestFilter filter;
TestFilter filterMock;
@Test
public void filtroNaoPreValidadoTest() {
filterMock = Mockito.spy(filter);
Mockito.doReturn(false).when(filterMock.preValidate(Mockito.any(CampaignVO.class)));
List<CampaignVO> campaignList = createCampaignList();
filterMock.doFilter(createSource(), campaignList);
}
O Mockito também consegue validar o
comportamento dos métodos reais,
verificando quantas vezes um método foi ou
não chamado, em qual ordem, etc
A validação de comportamento pode ser
muito útil em classes de transformações ou
validadores
O Mockito também consegue validar o
comportamento dos métodos reais,
verificando quantas vezes um método foi ou
não chamado, em qual ordem, etc
A validação de comportamento pode ser
muito útil em classes de transformações ou
validadores
Valido que uma chamada não ocorreu
@Autowired
TestFilter filter;
TestFilter filterMock;
@Test
public void filtroNaoPreValidadoTest() {
filterMock = Mockito.spy(filter);
Mockito.doReturn(false).when(filterMock.preValidate(Mockito.any(CampaignVO.class)));
List<CampaignVO> campaignList = createCampaignList();
filterMock.doFilter(createSource(), campaignList);
// Não passou na prevalidação não deve chamar o filtro
Mockito.verify(filterMock, Mockito.never()).filter(Mockito.any(CampaignVO.class),
Mockito.any(SourceVO.class));
}
Testar um validador.
public boolean validatesCampaignToAlter(CampaignVO campaignVO) {
boolean resp = false;
if (validateBanners(campaignVO) && validateStartDate(campaignVO) &&
validateCategory(campaignVO) && validateCountry(campaignVO) && validateId(campaignVO)) {
resp = true;
}
return resp;
}
@Test
public void alteracaoCampanhaNegadaSemBanner() {
CampaignVO campaign = new CampaignVO();
campaign.setHas_banners((byte) 0);
Assert.assertFalse(validatorSpy.validatesCampaignToAlter(campaign));
Mockito.verify(validatorSpy, Mockito.times(1)).validateBanners(campaign);
Mockito.verify(validatorSpy, Mockito.never()).validateStartDate(campaign);
Mockito.verify(validatorSpy, Mockito.never()).validateCategory(campaign);
Mockito.verify(validatorSpy, Mockito.never()).validateCountry(campaign);
Mockito.verify(validatorSpy, Mockito.never()).validateId(campaign);
Testes muitas vezes obriga a mudar atributos
privados de uma classe, como suas
dependências.
O Spring Testing possui uma classe chamada
ReflectionTestUtils com vários métodos úteis
// Adiciona o objeto sourceCheckerMock dentro do objeto businessMock,
// sendo esse atributo chamado “sourceChecker”
ReflectionTestUtils.setField(target, “atrributeName", objectToInsert);
Boolean slaveCrash = (Boolean) ReflectionTestUtils.getField(target, “attributeToRead");
O Spring Testing também possui algumas
ferramentas para se testar controllers e
emular chamadas HTTP
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/applicationContext.xml", "/springmvc-servlet.xml"})
public class CacheStatusControllerTest {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private CacheStatusController controller;
private MockHttpServletRequest request = new MockHttpServletRequest();
private MockHttpServletResponse response = new MockHttpServletResponse();
private AnnotationMethodHandlerAdapter handler;
Deve-se carregar o contexto da aplicação e o do MVC
Deve-se carregar o controller necessário
Deve-se criar um handler e um Mock do Request e Response
@Before
public void before() {
// Recupera handler para a chamada ao Controller
handler = applicationContext.getBean(AnnotationMethodHandlerAdapter.class);
// Habilita recuperação do conteúdo do response
response.setOutputStreamAccessAllowed(true);
}
O Handler deve ser associado o Handler usado no Spring (talvez seja um
pouco chato descobrir isso)
Caso deseje-se ler o conteúdo do response, o que é o mais comum, deve-se
setar o acesso ao OutputStream
@Test
public void validateCacheStatus() throws Exception {
// Prepara método e url de chamada
request.setMethod("GET");
request.setRequestURI("/status/cache.html");
request.setParameter(“update", “true");
handler.handle(request, response, controller);
Assert.assertEquals("Informações incorretas", expectedResponse(),
response.getContentAsString());
}
O request deve ser setado com o método desejado (GET,POST,PUT,etc)
A URL de ser setada na URI do request
Caso haja parâmetros esses devem ser setados no request
Para executar a chamada utilize o método handle do Handler capturado
Para ler a resposta, caso tenha setado essa opção no response, utilize o
método getContentAsString (ou outro formato desejado)
Quando utilizar o Spring como seu framework de
Injeção de Dependência, prefira sempre as
configurações por anotações ao invés do XML,
porém vale lembrar que essa última configuração
sobrescreve qualquer anotação feita.
Certos cenários de teste necessitam de situações
especiais, não hesite em configurar o contexto
para que a situação seja contemplada. Ex.: Ligar
ou desligar transações, ler outro arquivo de
propriedades, ligar ou desligar aspectos, etc.
Mockito
◦ http://code.google.com/p/mockito/
TDD
◦ http://pt.wikipedia.org/wiki/Test_Driven_Developm
ent
Spring Framework
◦ http://static.springsource.org/spring/docs/3.1.x/s
pring-framework-reference/html/
Spring Testing
◦ http://static.springsource.org/spring/docs/3.1.x/s
pring-framework-reference/html/testing.html

Mais conteúdo relacionado

Mais procurados

TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Androidtdc-globalcode
 
Excecoes
ExcecoesExcecoes
ExcecoesEMSNEWS
 
Mock objects - Teste de código com dependências
Mock objects - Teste de código com dependênciasMock objects - Teste de código com dependências
Mock objects - Teste de código com dependênciasDenis L Presciliano
 
Certificação Java: Exceções
Certificação Java: ExceçõesCertificação Java: Exceções
Certificação Java: ExceçõesEduardo Mendes
 
Android DevConference - Refactoring for RxJava
Android DevConference - Refactoring for RxJavaAndroid DevConference - Refactoring for RxJava
Android DevConference - Refactoring for RxJavaiMasters
 
Testes de Unidade - Unidade II
Testes de Unidade - Unidade IITestes de Unidade - Unidade II
Testes de Unidade - Unidade IIJoão Lourenço
 
Programação Concorrente - Gerenciamento de Threads - Parte II
Programação Concorrente - Gerenciamento de Threads - Parte IIProgramação Concorrente - Gerenciamento de Threads - Parte II
Programação Concorrente - Gerenciamento de Threads - Parte IIFabio Moura Pereira
 

Mais procurados (18)

TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
 
Junit 4.0
Junit 4.0Junit 4.0
Junit 4.0
 
Excecoes
ExcecoesExcecoes
Excecoes
 
POO - 22 - Tratamento de Exceções em Java
POO - 22 - Tratamento de Exceções em JavaPOO - 22 - Tratamento de Exceções em Java
POO - 22 - Tratamento de Exceções em Java
 
Mock objects - Teste de código com dependências
Mock objects - Teste de código com dependênciasMock objects - Teste de código com dependências
Mock objects - Teste de código com dependências
 
Palestra Testes De Unidade Com JUnit
Palestra Testes De Unidade Com JUnitPalestra Testes De Unidade Com JUnit
Palestra Testes De Unidade Com JUnit
 
Tratamento de exceções em Java
Tratamento de exceções em JavaTratamento de exceções em Java
Tratamento de exceções em Java
 
Java 06
Java 06Java 06
Java 06
 
Java 13 Excecoes
Java 13 ExcecoesJava 13 Excecoes
Java 13 Excecoes
 
Testes: Por onde Começar?
Testes: Por onde Começar?Testes: Por onde Começar?
Testes: Por onde Começar?
 
Java 12
Java 12Java 12
Java 12
 
TDD com Python (Completo)
TDD com Python (Completo)TDD com Python (Completo)
TDD com Python (Completo)
 
Certificação Java: Exceções
Certificação Java: ExceçõesCertificação Java: Exceções
Certificação Java: Exceções
 
Android DevConference - Refactoring for RxJava
Android DevConference - Refactoring for RxJavaAndroid DevConference - Refactoring for RxJava
Android DevConference - Refactoring for RxJava
 
Excepções JAVA
Excepções JAVAExcepções JAVA
Excepções JAVA
 
Erros, exceções e asserções
Erros, exceções e asserçõesErros, exceções e asserções
Erros, exceções e asserções
 
Testes de Unidade - Unidade II
Testes de Unidade - Unidade IITestes de Unidade - Unidade II
Testes de Unidade - Unidade II
 
Programação Concorrente - Gerenciamento de Threads - Parte II
Programação Concorrente - Gerenciamento de Threads - Parte IIProgramação Concorrente - Gerenciamento de Threads - Parte II
Programação Concorrente - Gerenciamento de Threads - Parte II
 

Destaque

Destaque (6)

Apache camel
Apache camelApache camel
Apache camel
 
Cassandra cql
Cassandra cqlCassandra cql
Cassandra cql
 
Ad server cassandra
Ad server cassandraAd server cassandra
Ad server cassandra
 
Tech Talk Buscapé - Redis
Tech Talk Buscapé - RedisTech Talk Buscapé - Redis
Tech Talk Buscapé - Redis
 
Tech Talk Buscapé - Clean Code
Tech Talk Buscapé - Clean CodeTech Talk Buscapé - Clean Code
Tech Talk Buscapé - Clean Code
 
Scalable CSS Architecture
Scalable CSS ArchitectureScalable CSS Architecture
Scalable CSS Architecture
 

Semelhante a TDD e testes unitários

TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Androidtdc-globalcode
 
Android: testes automatizados e TDD
Android: testes automatizados e TDDAndroid: testes automatizados e TDD
Android: testes automatizados e TDDDextra
 
Demoiselle Behave - Parte 3
Demoiselle Behave - Parte 3Demoiselle Behave - Parte 3
Demoiselle Behave - Parte 3Vanderson Silva
 
Minicurso Objective-C
Minicurso Objective-CMinicurso Objective-C
Minicurso Objective-CSaulo Arruda
 
TDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOSTDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOSFábio Miranda
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetrosMaurício Linhares
 
Teste de Integração - Unidade III
Teste de Integração - Unidade IIITeste de Integração - Unidade III
Teste de Integração - Unidade IIIJoão Lourenço
 
Fazendo Injeção de dependência com Unity 1.2
Fazendo Injeção de dependência com Unity 1.2Fazendo Injeção de dependência com Unity 1.2
Fazendo Injeção de dependência com Unity 1.2Giovanni Bassi
 
Testes de Unidade com Junit
Testes de Unidade com JunitTestes de Unidade com Junit
Testes de Unidade com Junitcejug
 
Mock it with mockito
Mock it with mockitoMock it with mockito
Mock it with mockitoRenan Uchôa
 
Design Patterns (MSDN Webcast)
Design Patterns (MSDN Webcast)Design Patterns (MSDN Webcast)
Design Patterns (MSDN Webcast)Giovanni Bassi
 
Mobileconf dicas-android
Mobileconf dicas-androidMobileconf dicas-android
Mobileconf dicas-androidAlberto Souza
 

Semelhante a TDD e testes unitários (20)

TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
 
Power mock
Power mockPower mock
Power mock
 
Android: testes automatizados e TDD
Android: testes automatizados e TDDAndroid: testes automatizados e TDD
Android: testes automatizados e TDD
 
Mock Objects
Mock ObjectsMock Objects
Mock Objects
 
Demoiselle Behave - Parte 3
Demoiselle Behave - Parte 3Demoiselle Behave - Parte 3
Demoiselle Behave - Parte 3
 
Minicurso Objective-C
Minicurso Objective-CMinicurso Objective-C
Minicurso Objective-C
 
TDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOSTDD - Algumas lições aprendidas com o livro GOOS
TDD - Algumas lições aprendidas com o livro GOOS
 
Spring MVC - QConSP
Spring MVC - QConSPSpring MVC - QConSP
Spring MVC - QConSP
 
Testes com JUnit
Testes com JUnitTestes com JUnit
Testes com JUnit
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetros
 
Teste de Integração - Unidade III
Teste de Integração - Unidade IIITeste de Integração - Unidade III
Teste de Integração - Unidade III
 
Fazendo Injeção de dependência com Unity 1.2
Fazendo Injeção de dependência com Unity 1.2Fazendo Injeção de dependência com Unity 1.2
Fazendo Injeção de dependência com Unity 1.2
 
Testes de Unidade com Junit
Testes de Unidade com JunitTestes de Unidade com Junit
Testes de Unidade com Junit
 
Mock it with mockito
Mock it with mockitoMock it with mockito
Mock it with mockito
 
Design Patterns (MSDN Webcast)
Design Patterns (MSDN Webcast)Design Patterns (MSDN Webcast)
Design Patterns (MSDN Webcast)
 
TDD Primeiro Contato
TDD Primeiro ContatoTDD Primeiro Contato
TDD Primeiro Contato
 
RMI em Java
RMI em JavaRMI em Java
RMI em Java
 
Mobileconf dicas-android
Mobileconf dicas-androidMobileconf dicas-android
Mobileconf dicas-android
 
Refactoring
RefactoringRefactoring
Refactoring
 
Introdução a tdd
Introdução a tddIntrodução a tdd
Introdução a tdd
 

TDD e testes unitários

  • 2. Estilo de desenvolvimento guiado pela criação de testes que validam a funcionalidade implementada antes da criação do código de produção ◦ Código mais simples ◦ Algoritmos confiáveis ◦ Menor custo de manutenção
  • 3.
  • 4. Aumento de complexidade em cenários de testes funcionais (interface de usuários, repositórios) Apoio gerencial Testes falhos causam programas falhos Testes de cobertura Lacunas de testes Falso senso de segurança (TDD não é bala de prata)
  • 5. Testes requerem visibilidade dos métodos Encapsulamento requer esconder métodos Use nomes de pacotes iguais ◦ Classe de produção está no pacote com.foo.bar ◦ Classe de teste deve ficar no pacote com.foo.bar Use modificadores protected e package (default)
  • 6. Testes requerem comportamento específicos Testes requerem objetos controláveis Testes requerem Mocks Frameworks de Mocks ◦ Mockito ◦ EasyMock ◦ PowerMock
  • 7. Framework de Mock ◦ Simples ◦ Claro ◦ Intuitivo (depois que você entende sua lógica) ◦ Versão atual 1.9.0 ◦ Documentação e notícias http://code.google.com/p/mockito/
  • 8. @Test public void myTest() { SomeObject myMock = Mockito.mock(SomeObject.class); } @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"/applicationContext.xml"}) public class SourceCheckerTest { @Autowired SourceChecker sourceChecker; @Mock SourceRepository mockRepository; @Before public void before() { MockitoAnnotations.initMocks(this); }
  • 9. Adiciona um comportamento a um dado método de um mock public SourceVO getSource(RequestVO request) { SourceVO sourceVO = null; sourceVO = repository.loadById(request.getSourceId()); … } @Test public void procuraSourceExistenteTest() throws RepositoryException { SourceVO sourceVO = getSourceVO(); String sourceId = sourceVO.getId().toString(); Mockito.when(mockRepository.loadById(sourceId)).thenReturn(sourceVO); RequestVO request = Given.request(); request.setSourceId(sourceId); SourceVO source = sourceChecker.getSource(request); … }
  • 10. //Retorna dado valor Mockito.when(mockRepository.loadById(sourceId)).thenReturn(sourceVO); //Retorna exceção Mockito.when(mockRepository.loadById(sourceId)).thenThrow(new NullPointerException()); //Chama o método real Mockito.when(mockRepository.loadById(sourceId)).thenCallRealMethod(); //Cria uma resposta customizada Mockito.when(mockRepository.loadById(sourceId)).thenAnswer(…);
  • 11. //Retorna dado valor Mockito.when(counter.getId()).thenReturn(1).thenReturn(2).thenReturn(3). thenThrow(new NullPointerException()); É possível programar ações consecutivas para um dado método. Muito útil quando se quer ações diferentes a cada chamada de método. Ex.: Loop
  • 12. Mock é feito com a comparação de objetos, muitas vezes não temos o objeto exato para se comparar Mockito.when(lotteryMock.theChosenOne(Mockito.anyMap())).thenReturn(categId); Mockito.any(); Mockito.any(CampaignVO.class); Mockito.anyBoolean(); Mockito.anyInt(); Mockito.anyCollection(); Mockito.anyCollectionOf(String.class); Mockito.anyList(); Mockito.anyListOf(Integer.class); Mockito.anyVararg(); Matchers customizados também podem ser criados mas a sua utilização é muito rara
  • 13. Métodos void são um caso a parte para o Mockito pois o when recebe o método a ser mockado como parâmetro e o compilador java não aceita isso public static void main(String[] args) { System.out.println(getNum()); //OK System.out.println(getVoid()); // ERROR } private static Integer getNum() { return 5; } private static void getVoid() { }
  • 14. Uso dos métodos doThrow e doCallRealMethod Mockito.doThrow(NullPointerException.class).when(sourceRepository).loadById("123456"); Mockito.doCallRealMethod().when(sourceRepository).loadById("123456");
  • 15. Os mocks conseguem retornar objetos controlados mas as vezes deseja-se interceptar a chamada para alterar a resposta, verificar os parâmetros passados e executar ou não o método real para isso existe o Answer Evite usar answer, procure soluções mais simples.
  • 16. Dentro do AdServer o Answer foi usado para validar a passagem de argumentos em métodos complexos public void makeSearch(CampaignVO campaign) { changeCampaignName(campaign); changeOtherValue(campaign); repository.search(campaign); // What are the campaign's attributes? } Ex.: Desejo validar a campanha passada no repositório já que essa campanha pode ter sido alterada por métodos intermediários
  • 17. Mockito.doAnswer(new Answer<Map<Long, Double>>() { public Map<Long, Double> answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); // valida país recebido List<AdVO> adVO = (List<AdVO>) args[0]; Assert.assertTrue(adVO.size() == 1); Assert.assertEquals("728_90", adVO.get(0).getDimension()); return values; } }).when(adSelectorSpy).createAdsValues(adList); Valido se o primeiro argumento passado possui um elemento e se esse elemento tem um valor específico
  • 18. O que acontece se você deseja controlar apenas uma parte de um objeto? ◦ Ex.: Deseja-se testar um método que chama outro método dentro da mesma classe @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"/applicationContext.xml"}) public class SourceCheckerTest { @Autowired SourceChecker sourceChecker; SourceChecker checkerSpy; @Before public void before() { checkerSpy = Mockito.spy(sourceChecker); } Espiamos o comportamento de um método real
  • 19. Um pouco de teoria ◦ Quando um método é mockado ele é executado, porém como ele não existe, não há problema ◦ Mockar um método de um objeto espionado faz o método ser executado, porém como ele é real isso pode causar problemas ◦ Spies devem usar métodos doThrow, doReturn e doNothing ◦ MOCKS NUNCA executam métodos reais até que digamos o contrário (thenCallRealMethod ou doCallRealMethod), SPIES SEMPRE executam métodos reais até que digamos o contrário (doNothing)
  • 20. @Autowired TestFilter filter; TestFilter filterMock; @Test public void filtroNaoPreValidadoTest() { filterMock = Mockito.spy(filter); Mockito.doReturn(false).when(filterMock.preValidate(Mockito.any(CampaignVO.class))); List<CampaignVO> campaignList = createCampaignList(); filterMock.doFilter(createSource(), campaignList); }
  • 21. O Mockito também consegue validar o comportamento dos métodos reais, verificando quantas vezes um método foi ou não chamado, em qual ordem, etc A validação de comportamento pode ser muito útil em classes de transformações ou validadores
  • 22. O Mockito também consegue validar o comportamento dos métodos reais, verificando quantas vezes um método foi ou não chamado, em qual ordem, etc A validação de comportamento pode ser muito útil em classes de transformações ou validadores
  • 23. Valido que uma chamada não ocorreu @Autowired TestFilter filter; TestFilter filterMock; @Test public void filtroNaoPreValidadoTest() { filterMock = Mockito.spy(filter); Mockito.doReturn(false).when(filterMock.preValidate(Mockito.any(CampaignVO.class))); List<CampaignVO> campaignList = createCampaignList(); filterMock.doFilter(createSource(), campaignList); // Não passou na prevalidação não deve chamar o filtro Mockito.verify(filterMock, Mockito.never()).filter(Mockito.any(CampaignVO.class), Mockito.any(SourceVO.class)); }
  • 24. Testar um validador. public boolean validatesCampaignToAlter(CampaignVO campaignVO) { boolean resp = false; if (validateBanners(campaignVO) && validateStartDate(campaignVO) && validateCategory(campaignVO) && validateCountry(campaignVO) && validateId(campaignVO)) { resp = true; } return resp; } @Test public void alteracaoCampanhaNegadaSemBanner() { CampaignVO campaign = new CampaignVO(); campaign.setHas_banners((byte) 0); Assert.assertFalse(validatorSpy.validatesCampaignToAlter(campaign)); Mockito.verify(validatorSpy, Mockito.times(1)).validateBanners(campaign); Mockito.verify(validatorSpy, Mockito.never()).validateStartDate(campaign); Mockito.verify(validatorSpy, Mockito.never()).validateCategory(campaign); Mockito.verify(validatorSpy, Mockito.never()).validateCountry(campaign); Mockito.verify(validatorSpy, Mockito.never()).validateId(campaign);
  • 25. Testes muitas vezes obriga a mudar atributos privados de uma classe, como suas dependências. O Spring Testing possui uma classe chamada ReflectionTestUtils com vários métodos úteis // Adiciona o objeto sourceCheckerMock dentro do objeto businessMock, // sendo esse atributo chamado “sourceChecker” ReflectionTestUtils.setField(target, “atrributeName", objectToInsert); Boolean slaveCrash = (Boolean) ReflectionTestUtils.getField(target, “attributeToRead");
  • 26. O Spring Testing também possui algumas ferramentas para se testar controllers e emular chamadas HTTP
  • 27. @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"/applicationContext.xml", "/springmvc-servlet.xml"}) public class CacheStatusControllerTest { @Autowired private ApplicationContext applicationContext; @Autowired private CacheStatusController controller; private MockHttpServletRequest request = new MockHttpServletRequest(); private MockHttpServletResponse response = new MockHttpServletResponse(); private AnnotationMethodHandlerAdapter handler; Deve-se carregar o contexto da aplicação e o do MVC Deve-se carregar o controller necessário Deve-se criar um handler e um Mock do Request e Response
  • 28. @Before public void before() { // Recupera handler para a chamada ao Controller handler = applicationContext.getBean(AnnotationMethodHandlerAdapter.class); // Habilita recuperação do conteúdo do response response.setOutputStreamAccessAllowed(true); } O Handler deve ser associado o Handler usado no Spring (talvez seja um pouco chato descobrir isso) Caso deseje-se ler o conteúdo do response, o que é o mais comum, deve-se setar o acesso ao OutputStream
  • 29. @Test public void validateCacheStatus() throws Exception { // Prepara método e url de chamada request.setMethod("GET"); request.setRequestURI("/status/cache.html"); request.setParameter(“update", “true"); handler.handle(request, response, controller); Assert.assertEquals("Informações incorretas", expectedResponse(), response.getContentAsString()); } O request deve ser setado com o método desejado (GET,POST,PUT,etc) A URL de ser setada na URI do request Caso haja parâmetros esses devem ser setados no request Para executar a chamada utilize o método handle do Handler capturado Para ler a resposta, caso tenha setado essa opção no response, utilize o método getContentAsString (ou outro formato desejado)
  • 30. Quando utilizar o Spring como seu framework de Injeção de Dependência, prefira sempre as configurações por anotações ao invés do XML, porém vale lembrar que essa última configuração sobrescreve qualquer anotação feita. Certos cenários de teste necessitam de situações especiais, não hesite em configurar o contexto para que a situação seja contemplada. Ex.: Ligar ou desligar transações, ler outro arquivo de propriedades, ligar ou desligar aspectos, etc.
  • 31. Mockito ◦ http://code.google.com/p/mockito/ TDD ◦ http://pt.wikipedia.org/wiki/Test_Driven_Developm ent Spring Framework ◦ http://static.springsource.org/spring/docs/3.1.x/s pring-framework-reference/html/ Spring Testing ◦ http://static.springsource.org/spring/docs/3.1.x/s pring-framework-reference/html/testing.html