O objetivo da segunda aula do curso de testes unitários com Angular 2, é ensinar como testar serviços e filtros
1. Introdução
Agora que você já sabe a estrutura dos testes unitários em um projeto Angular 2, chegou a hora de aprender a criar os testes.
Nessa aula você aprenderá a testar filtros (pipes) e serviços (services), e no final você também aprenderá como realizar o debug dos testes no navegador utilizando o Karma.
Mas antes de iniciar com os testes unitários, você deverá criar um novo filtro para o projeto, que será utilizado para a criação dos testes unitários.
Então vamos iniciar!
2. Criando um filtro (pipe)
O filtro (pipe) a ser criado para o teste será um filtro de formatação do ID do cliente.
Visto que o ID é o timestamp atual, que é um número de 13 dígitos que representa a data e hora do cadastro, você irá aplicar um formatação para ele.
O primeiro passo então é criar o arquivo ‘cliente-id.pipe.ts’ em ‘src/app/cliente/shared’, com o seguinte conteúdo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | /** * Filtro/Pipe de formatação do ID do cliente. * * @author Márcio Casale de Souza <contato@kazale.com> * @since 0.0.5 */ import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'clienteId' }) export class ClienteIdPipe implements PipeTransform { transform(id: any): string { let idTexto: string = String(id); if (idTexto.length !== 13) { return idTexto; } return idTexto.substr(0, 4) + '-' + idTexto.substr(4, 7) + '/' + idTexto.substr(11, 2); } } |
O código acima é um filtro padrão do Angular 2, que retornará um valor formatado com a máscara ‘####.#######/##’.
Vamos aproveitar e configurar o filtro criado na aplicação.
Adicione a seguinte entrada ao arquivo ‘src/app/cliente/shared/index.ts’:
1 | export * from './cliente-id.pipe'; |
Registre o filtro no módulo do cliente, para isso adicione no arquivo ‘src/app/cliente/cliente.module.ts’:
1 2 3 4 5 6 7 8 9 10 | import { ClienteIdPipe } from './'; ... @NgModule({ declarations: [ ... ClienteIdPipe ], ... }) export class ClienteModule {} |
Agora você deverá chamar o novo filtro no template de listagem de clientes, para isso edite o arquivo ‘src/app/cliente/listar/cliente-listar.component.html’:
1 2 3 4 5 | ... <tr *ngFor="let cliente of clientes"> <td>{{ cliente.id | clienteId }}</td> <td>{{ cliente.nome }}</td> ... |
Por fim, edite o arquivo de testes do componente de listagem de clientes ‘src/app/cliente/cliente-listar.component.spec.ts’, e desabilite o teste padrão, que devido ao novo filtro passará a falhar:
1 2 3 4 5 | ... xit('deve garantir que o componente tenha sido criado', () => { expect(fixture).toBeDefined(); }); ... |
Você aprenderá a corrigir esse erro na próxima aula, onde aprenderá a criar testes unitários para componentes.
3. Criando o teste unitário para o filtro (pipe)
Vamos começar aprendendo a criar testes unitários para o filtro (pipe) criado no tópico anterior.
Esse teste será do tipo teste unitário isolado, onde basicamente será criada uma instância do filtro, e seu método ‘transform’ será chamado diretamente.
Para os testes serão utilizados os recursos do Jasmine para as verificações, e a execução ficará por conta do Karma.
Crie o arquivo ‘src/app/cliente/shared/cliente-id.pipe.spec.ts’ com o seguinte conteúdo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import { ClienteIdPipe } from './'; describe('Suíte de testes de formatação do id do cliente', () => { let clienteIdPipe: ClienteIdPipe; beforeEach(() => { clienteIdPipe = new ClienteIdPipe(); }); it('deve retornar o valor do id formatado como ####-#######/##', () => { expect(clienteIdPipe.transform('1234567890123')).toEqual('1234-5678901/23'); }); it('deve retornar o mesmo valor quando id não conter 13 digitos', () => { expect(clienteIdPipe.transform('12345')).toEqual('12345'); expect(clienteIdPipe.transform('12345678901234')).toEqual('12345678901234'); }); }); |
Conforme observado no código acima, temos algumas funções novas, que fazem parte do Jasmine.
Abaixo seguem as descrições dos elementos do Jasmine utilizados no código de teste do filtro:
Função da API do Jasmine | Descrição |
---|---|
describe | Serve para criar uma suíte de testes, ou seja, um agrupamento de testes dado um contexto. Recebe como parâmetros a descrição do contexto da suíte, e uma função que conterá todos os testes da suíte. |
it | Serve para criar um novo teste. Uma suíte pode conter um ou mais testes. Recebe como parâmetros a descrição do teste, e uma função que conterá as verificações do teste. |
beforeEach | Serve para executar ações antes de cada teste definido com a função ‘it’. Utilizado para inicializar ou restaurar valores antes da execução de cada teste. |
expect | Serve para validar uma expectativa. Essa função recebe o resultado da execução do que se deseja testar, que será validada através de uma validador como o ‘toEqual’, que será descrito a seguir. |
toEqual | Serve para validar o resultado de uma operação a ser testada. É utilizada em conjunto com o ‘expect’ para verificar uma operação, que nesse caso valida se os valores são iguais. |
Para executar os testes digite no terminal, na raiz do projeto:
1 | npm run test |
4. Criando o teste unitário para o serviço (service)
Testes unitários isolados de serviços são executados da mesma forma que os de filtros.
Primeiramente você deverá criar uma instância do serviço, e após isso basta utilizá-la para fazer chamadas aos métodos contidos nele.
Edite o arquivo ‘app/src/cliente/shared/cliente.service.spec.ts’, e adicione o seguinte conteúdo nele:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | /** * Arquivo de teste do componente ClienteService. * * @author Márcio Casale de Souza <contato@kazale.com> * @since 0.0.3 */ import { ClienteService, Cliente } from './'; describe('Suíte de testes do serviço de cliente', () => { let clienteService: ClienteService; let cliente: Cliente; let cliente2: Cliente; beforeEach(() => { clienteService = new ClienteService(); cliente = new Cliente(1234567890123, 'Fulano'); cliente2 = new Cliente(9876543210123, 'Ciclano'); delete sessionStorage['clientes']; }); it ('deve cadastrar um cliente', () => { clienteService.cadastrar(cliente); let clienteCad = clienteService.buscarPorId(cliente.id); expect(clienteCad).toBeDefined(); expect(clienteCad.id).toEqual(cliente.id); expect(clienteCad.nome).toEqual(cliente.nome); }); it ('deve listar todos os clientes', () => { clienteService.cadastrar(cliente); clienteService.cadastrar(cliente2); let clientes: Cliente[] = clienteService.listarTodos(); expect(clientes).toBeDefined(); expect(clientes.length).toEqual(2); expect(clientes[0].id).toEqual(cliente.id); expect(clientes[1].id).toEqual(cliente2.id); }); }); |
No código acima introduzimos o uso do ‘toBeDefined’, que basicamente retorna se um objeto foi definido ou não.
Como o serviço possui a persistência no ‘sessionStorage’, não existe a necessidade de criar objetos falsos para simular seu comportamento, conforme você aprenderá ao testar componentes.
Repare também que no ‘beforeEach’, ou seja, antes de executar um teste, removemos os dados contidos no ‘sessionStorage’, para que ele não interfira em outros testes.
5. Aprendendo a fazer debug dos testes
O debug pode ser um recursos imprescindível em determinadas ocasiões, e como desenvolvemos em Typescript, nem sempre é tão fácil realizar o debug de um código.
Para nossa sorte, o Karma possui um recurso de debug que é excelente para fazermos o debug de uma aplicação olhando diretamente para o código fonte Typescript!
Para habilitar o modo de debug execute os testes em modo de escuta, com o seguinte comando no terminal, na raiz da aplicação:
1 | npm run test |
Na janela do navegador Chrome que será aberta, clique no botão ‘DEBUG’.
Uma nova aba será aberta. Nessa aba, clique com o botão direito na tela, e em ‘Inspect’.
No inspector que será exibido, clique na aba ‘Sources’.
Na estrutura de arquivos exibida, selecione o arquivo que deseja realizar o debug, e clique nele.
O código será exibido, agora basta clicar no número da linha desejada para adicionar breakpoints, que são os locais onde você deseja visualizar na execução do código.
Por fim, atualize a página para executar os testes e visualizar o código a ser feito o debug.
Utilize os controles exibidos ao lado do código, para navegar entre as linhas e verificar os passos da execução.
6. Conclusão
Conforme estudado nessa aula, foi possível ver como os testes unitários são práticos e fáceis de serem criados.
Sua grande vantagem é que por serem testes específicos, não precisamos lidar com dependências, muitas configurações, é tudo bastante simples e direto.
Para sua criação é importante ter um entendimento do Jasmine, pois assim será mais fácil explorar as possibilidades do que podemos testar, mas como disse na aula anterior, não se preocupe com isso agora, pois ao término do curso, tenho uma surpresa para te ajudar com esse aprendizado.
Recomendo assinar nossa newsletter para receber atualizações de lançamento de novas aulas, para isso basta preencher o formulário abaixo:
Nos vemos na próxima aula, até lá!