Este tutorial aborda a implementação de um teste de unidade que valida o comportamento do Modelo do Sling do componente Byline, criado no Componente personalizado tutorial.
Revise as ferramentas necessárias e as instruções para configurar um ambiente de desenvolvimento local.
Se o Java™ 8 e o Java™ 11 estiverem instalados no sistema, o executador de teste do Código VS poderá escolher o tempo de execução mais baixo do Java™ ao executar os testes, resultando em falhas de teste. Se isso ocorrer, desinstale o Java™ 8.
Se você concluiu o capítulo anterior com êxito, é possível reutilizar o projeto e ignorar as etapas para verificar o projeto inicial.
Confira o código base que o tutorial constrói:
Confira o tutorial/unit-testing-start
ramificação de GitHub
$ cd aem-guides-wknd
$ git checkout tutorial/unit-testing-start
Implante a base de código em uma instância de AEM local usando suas habilidades Maven:
$ mvn clean install -PautoInstallSinglePackage
Se estiver usando AEM 6.5 ou 6.4, anexe a classic
para qualquer comando Maven.
$ mvn clean install -PautoInstallSinglePackage -Pclassic
Você sempre pode exibir o código concluído em GitHub ou faça check-out do código localmente, alternando para a ramificação tutorial/unit-testing-start
.
Neste tutorial, exploraremos como escrever Testes de unidade para o componente Byline Modelo Sling (criado na Criação de um componente de AEM personalizado). Os testes de unidade são testes de tempo de criação gravados em Java™ que verificam o comportamento esperado do código Java™. Normalmente, cada teste de unidade é pequeno e valida a saída de um método (ou unidades de trabalho) em relação aos resultados esperados.
Usamos AEM práticas recomendadas e empregamos:
Adobe Cloud Manager integra a execução do teste de unidade e relatório de cobertura de código no seu pipeline de CI/CD para ajudar a incentivar e promover as melhores práticas de teste de unidade AEM código.
Embora o código de teste de unidade seja uma boa prática para qualquer base de código, ao usar o Cloud Manager, é importante aproveitar seus recursos de teste e relatório de qualidade de código fornecendo testes de unidade para que o Cloud Manager seja executado.
O primeiro passo é inspecionar as dependências de Maven para suportar a gravação e a execução dos testes. Há quatro dependências necessárias:
O JUnit5, Mockito e AEM Mocks** as dependências de teste são adicionadas automaticamente ao projeto durante a configuração usando o AEM arquétipo Maven.
Para exibir essas dependências, abra o POM do reator pai em aem-guides-wknd/pom.xml, navegue até o <dependencies>..</dependencies>
e visualize as dependências para JUnit, Mockito, Mocks do Apache Sling e Testes de Mock AEM por io.wcm em <!-- Testing -->
.
Certifique-se de que io.wcm.testing.aem-mock.junit5
está definida como 4.1.0:
<dependency>
<groupId>io.wcm</groupId>
<artifactId>io.wcm.testing.aem-mock.junit5</artifactId>
<version>4.1.0</version>
<scope>test</scope>
</dependency>
Arquétipo 35º gera o projeto com io.wcm.testing.aem-mock.junit5
version 4.1.8. Faça o download para 4.1.0 para seguir o restante deste capítulo.
Abrir aem-guides-wknd/core/pom.xml e veja se as dependências de teste correspondentes estão disponíveis.
Uma pasta de origem paralela no núcleo projeto conterá os testes de unidade e quaisquer arquivos de teste de suporte. Essa teste A pasta fornece a separação das classes de teste do código-fonte, mas permite que os testes atuem como se estivessem nos mesmos pacotes que o código-fonte.
Os testes de unidade normalmente mapeiam de 1 a 1 com classes Java™. Neste capítulo, escreveremos um teste JUnit para o BylineImpl.java, que é o Modelo do Sling que suporta o componente Byline.
Local onde são armazenados os testes de unidade.
Crie um teste de unidade para a BylineImpl.java
fazendo uma nova classe Java™ no src/test/java
em uma estrutura de pastas do pacote Java™ que espelha a localização da classe Java™ a ser testada.
Como estamos testando
src/main/java/com/adobe/aem/guides/wknd/core/models/impl/BylineImpl.java
criar uma classe de teste de unidade correspondente em Java™ em
src/test/java/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.java
O Test
sufixo no ficheiro de ensaio da unidade, BylineImplTest.java
é uma convenção que nos permite
BylineImpl.java
BylineImpl.java
Nesse ponto, o arquivo de teste JUnit é uma classe Java™ vazia.
Atualize o arquivo com o seguinte código:
package com.adobe.aem.guides.wknd.core.models.impl;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class BylineImplTest {
@BeforeEach
void setUp() throws Exception {
}
@Test
void testGetName() {
fail("Not yet implemented");
}
@Test
void testGetOccupations() {
fail("Not yet implemented");
}
@Test
void testIsEmpty() {
fail("Not yet implemented");
}
}
O primeiro método public void setUp() { .. }
tem anotações com JUnit's @BeforeEach
, que instrui o executador de teste JUnit a executar esse método antes de executar cada método de teste nesta classe. Isso fornece um local útil para inicializar um estado de teste comum exigido por todos os testes.
Os métodos subsequentes são os métodos de teste, cujos nomes recebem o prefixo test
por convenção e marcados com @Test
anotação. Observe que, por padrão, todos os nossos testes estão definidos para falhar, pois ainda não os implementamos.
Para começar, começamos com um único método de teste para cada método público na classe que estamos testando, portanto:
BylineImpl.java | BylineImplTest.java | |
---|---|---|
getName() | é testado por | testGetName() |
getOccupations() | é testado por | testGetOccupations() |
isEmpty() | é testado por | testIsEmpty() |
Esses métodos podem ser expandidos conforme necessário, como veremos mais adiante neste capítulo.
Quando essa classe de teste JUnit (também conhecida como caso de teste JUnit) é executada, cada método marcado com o @Test
será executado como um teste que pode ser aprovado ou falhar.
core/src/test/java/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.java
Execute o caso de teste JUnit clicando com o botão direito do mouse no BylineImplTest.java
e tocar em Executar.
Como esperado, todos os testes falharam, pois ainda não foram implementados.
Clique com o botão direito do mouse em BylineImplTests.java > Executar
Ao gravar testes de unidade, há duas abordagens principais:
Neste tutorial, a última abordagem é usada (já que criamos um BylineImpl.java em um capítulo anterior). Por isso, devemos rever e entender os comportamentos dos seus métodos públicos, mas também alguns dos seus detalhes de implementação. Isto pode parecer contrário, uma vez que um bom teste só deve incidir sobre os fatores de produção e os resultados, contudo, quando se trabalha em AEM, há várias considerações de implementação que têm de ser compreendidas para se construírem ensaios de trabalho.
O TDD no contexto de AEM requer um nível de especialização e é melhor adotado por AEM desenvolvedores com capacidade AEM desenvolvimento e teste de unidade de código AEM.
A maioria dos códigos escritos para AEM depende de APIs JCR, Sling ou AEM, que, por sua vez, exigem que o contexto de um AEM em execução seja executado corretamente.
Como os testes de unidade são executados na criação, fora do contexto de uma instância de AEM em execução, não há esse contexto. Para facilitar esta tarefa, mocks de AEM do wcm.io cria um contexto de modelo que permite que essas APIs maioria agir como se estivessem em AEM.
Criar um contexto de AEM usando wcm.io's AemContext
em BylineImplTest.java adicionando-o como uma extensão JUnit decorada com @ExtendWith
para BylineImplTest.java arquivo. A extensão cuida de todas as tarefas de inicialização e limpeza necessárias. Crie uma variável de classe para AemContext
que pode ser utilizado para todos os métodos de ensaio.
import org.junit.jupiter.api.extension.ExtendWith;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
...
@ExtendWith(AemContextExtension.class)
class BylineImplTest {
private final AemContext ctx = new AemContext();
Essa variável, ctx
, expõe um modelo AEM contexto que fornece algumas abstrações AEM e Sling:
O ctx
O objeto atuará como o ponto de entrada para a maior parte do nosso contexto de modelo.
No setUp(..)
, que é executado antes de cada @Test
, defina um estado de teste de modelo comum:
@BeforeEach
public void setUp() throws Exception {
ctx.addModelsForClasses(BylineImpl.class);
ctx.load().json("/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.json", "/content");
}
addModelsForClasses
registra o Modelo do Sling a ser testado, no modelo AEM Contexto, para que possa ser instanciado no @Test
métodos.load().json
carrega estruturas de recursos no contexto do modelo, permitindo que o código interaja com esses recursos como se fossem fornecidos por um repositório real. As definições de recursos no arquivo BylineImplTest.json
são carregadas no contexto mock JCR em /conteúdo.BylineImplTest.json
ainda não existe, portanto, vamos criá-lo e definir as estruturas de recurso do JCR necessárias para o teste.Os arquivos JSON que representam as estruturas de recursos do modelo são armazenados em core/src/test/resources seguindo o mesmo caminho de pacote que o arquivo de teste JUnit Java™.
Criar um arquivo JSON em core/test/resources/com/adobe/aem/guides/wknd/core/models/impl
nomeado BylineImplTest.json com o seguinte conteúdo:
{
"byline": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/content/byline"
}
}
Esse JSON define um recurso mock (nó JCR) para o teste de unidade do componente Byline. Nesse ponto, o JSON tem o conjunto mínimo de propriedades necessárias para representar um recurso de conteúdo do componente Byline, a variável jcr:primaryType
e sling:resourceType
.
Uma regra geral ao trabalhar com testes de unidade é criar o conjunto mínimo de conteúdo, contexto e código do mock necessário para satisfazer cada teste. Evite a tentação de construir um contexto de zombaria completo antes de escrever os testes, pois isso geralmente resulta em artefatos desnecessários.
Agora com a existência de BylineImplTest.json, quando ctx.json("/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.json", "/content")
for executado, as definições de recurso mock serão carregadas no contexto no caminho /conteúdo.
Agora que temos uma configuração básica de contexto de modelo, vamos escrever nosso primeiro teste para GetName() de BylineImpl. Este ensaio deve assegurar o método getName() retorna o nome de autoria correto armazenado no " do recurso name" propriedade.
Atualize o testGetName() método em BylineImplTest.java como se segue:
import com.adobe.aem.guides.wknd.core.models.Byline;
...
@Test
public void testGetName() {
final String expected = "Jane Doe";
ctx.currentResource("/content/byline");
Byline byline = ctx.request().adaptTo(Byline.class);
String actual = byline.getName();
assertEquals(expected, actual);
}
String expected
define o valor esperado. Definiremos como "Jane Concluída".ctx.currentResource
define o contexto do recurso mock para avaliar o código, para que isso seja definido como /content/byline já que é onde o recurso de conteúdo mock by line é carregado.Byline byline
instancia o Modelo de sling Byline adaptando-o do objeto de solicitação de mock.String actual
chama o método que estamos testando. getName()
, no objeto Modelo de sling em linha.assertEquals
afirma que o valor esperado corresponde ao valor retornado pelo objeto do Modelo de sling byline. Se esses valores não forem iguais, o teste falhará.Execute o teste… e ele falhará com um NullPointerException
.
Este teste NÃO falha porque nunca definimos um valor de name
no mock JSON, que fará com que o teste falhe, no entanto, a execução do teste não chegou a esse ponto! Esse teste falha devido a um NullPointerException
no próprio objeto byline.
No BylineImpl.java
, se @PostConstruct init()
O aciona uma exceção, pois impede que o Modelo do Sling instancie e faz com que o objeto do Modelo do Sling seja nulo.
@PostConstruct
private void init() {
image = modelFactory.getModelFromWrappedRequest(request, request.getResource(), Image.class);
}
Acontece que, embora o serviço OSGi ModelFactory seja fornecido por meio do AemContext
(por meio do Contexto do Apache Sling), nem todos os métodos são implementados, incluindo getModelFromWrappedRequest(...)
que é chamado em BylineImpl's init()
método . Isso resulta em uma AbstractMethodError, as causas init()
para falhar e a consequente adaptação do ctx.request().adaptTo(Byline.class)
é um objeto nulo.
Como os modelos fornecidos não podem acomodar nosso código, precisamos implementar o contexto do modelo nós mesmos Para isso, podemos usar o Mockito para criar um objeto ModeloFactory mock, que retorna um objeto de imagem mock quando getModelFromWrappedRequest(...)
é chamado sobre ele.
Como para até mesmo instanciar o Modelo do Sling Byline, esse contexto do modelo deve estar em vigor, podemos adicioná-lo ao @Before setUp()
método . Precisamos também de adicionar o MockitoExtension.class
para @ExtendWith
anotação acima da BylineImplTest classe .
package com.adobe.aem.guides.wknd.core.models.impl;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.Mock;
import com.adobe.aem.guides.wknd.core.models.Byline;
import com.adobe.cq.wcm.core.components.models.Image;
import io.wcm.testing.mock.aem.junit5.AemContext;
import io.wcm.testing.mock.aem.junit5.AemContextExtension;
import org.apache.sling.models.factory.ModelFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.apache.sling.api.resource.Resource;
@ExtendWith({ AemContextExtension.class, MockitoExtension.class })
public class BylineImplTest {
private final AemContext ctx = new AemContext();
@Mock
private Image image;
@Mock
private ModelFactory modelFactory;
@BeforeEach
public void setUp() throws Exception {
ctx.addModelsForClasses(BylineImpl.class);
ctx.load().json("/com/adobe/aem/guides/wknd/core/models/impl/BylineImplTest.json", "/content");
lenient().when(modelFactory.getModelFromWrappedRequest(eq(ctx.request()), any(Resource.class), eq(Image.class)))
.thenReturn(image);
ctx.registerService(ModelFactory.class, modelFactory, org.osgi.framework.Constants.SERVICE_RANKING,
Integer.MAX_VALUE);
}
@Test
void testGetName() { ...
}
@ExtendWith({AemContextExtension.class, MockitoExtension.class})
marca a classe Caso de teste a ser executada com Extensão Jupiter do Mockito JUnit o que permite o uso das anotações @Mock para definir objetos mock no nível Class.@Mock private Image
cria um objeto mock do tipo com.adobe.cq.wcm.core.components.models.Image
. Isso é definido no nível da classe para que, conforme necessário, @Test
métodos podem alterar seu comportamento conforme necessário.@Mock private ModelFactory
cria um objeto modelo do tipo ModelFactory. Este é um modelo puro de Mockito e não tem métodos implementados nele. Isso é definido no nível da classe para que, conforme necessário, @Test
métodos podem alterar seu comportamento conforme necessário.when(modelFactory.getModelFromWrappedRequest(..)
registra o comportamento mock para quando getModelFromWrappedRequest(..)
é chamado no objeto modeloFactory . O resultado definido em thenReturn (..)
é retornar o objeto de modelo de Imagem. Esse comportamento é chamado somente quando: o primeiro parâmetro é igual a ctx
Objeto de solicitação do , o segundo parâmetro é qualquer objeto de Recurso e o terceiro parâmetro deve ser a classe Imagem dos componentes principais . Aceitamos qualquer recurso porque ao longo de nossos testes definimos a variável ctx.currentResource(...)
para vários recursos mock definidos na variável BylineImplTest.json. Observe que adicionamos a variável lenient() rigor porque desejaremos, mais tarde, substituir esse comportamento do ModelFactory.ctx.registerService(..)
. registra o objeto modeloFactory no AemContext, com a classificação de serviço mais alta. Isso é necessário, pois o ModelFactory usado no init()
é injetado através do @OSGiService ModelFactory model
campo. Para o AemContext injetar our objeto mock, que lida com chamadas para getModelFromWrappedRequest(..)
, devemos registrá-lo como o Serviço de classificação mais alta desse tipo (ModelFactory).Execute o teste novamente e, novamente, ele falhará, mas desta vez a mensagem estará clara do motivo do seu erro.
Falha de testGetName() devido à asserção
Recebemos um AssertionError o que significa que a condição de asserção no teste falhou, e isso nos informa o o valor esperado é "Jane Doe" mas o o valor real é nulo. Isso faz sentido porque o "name" propriedade não foi adicionada ao mock /content/byline definição de recurso em BylineImplTest.json, então vamos adicioná-lo:
Atualizar BylineImplTest.json para definir "name": "Jane Doe".
{
"byline": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/content/byline",
"name": "Jane Doe"
}
}
Execute novamente o teste e testGetName()
agora passa!
Muito bem! O primeiro teste foi bem-sucedido! Vamos continuar e testar getOccupations()
. Como a inicialização do contexto do modelo foi feita no @Before setUp()
está disponível para todos @Test
métodos neste caso de teste, incluindo getOccupations()
.
Lembre-se de que esse método deve retornar uma lista de ocupações (decrescentes) classificadas alfabeticamente armazenada na propriedade de ocupações.
Atualizar testGetOccupations()
como se segue:
import java.util.List;
import com.google.common.collect.ImmutableList;
...
@Test
public void testGetOccupations() {
List<String> expected = new ImmutableList.Builder<String>()
.add("Blogger")
.add("Photographer")
.add("YouTuber")
.build();
ctx.currentResource("/content/byline");
Byline byline = ctx.request().adaptTo(Byline.class);
List<String> actual = byline.getOccupations();
assertEquals(expected, actual);
}
List<String> expected
defina o resultado esperado.ctx.currentResource
define o recurso atual para avaliar o contexto em relação à definição de recurso de modelo em /content/byline. Isso garante que o BylineImpl.java é executado no contexto do nosso recurso mock.ctx.request().adaptTo(Byline.class)
instancia o Modelo de sling Byline adaptando-o do objeto de solicitação de mock.byline.getOccupations()
chama o método que estamos testando. getOccupations()
, no objeto Modelo de sling em linha.assertEquals(expected, actual)
afirma que a lista esperada é igual à lista real.Lembre-se, como getName()
acima, a variável BylineImplTest.json não define ocupações, portanto, esse teste falhará se for executado, já que byline.getOccupations()
retornará uma lista vazia.
Atualizar BylineImplTest.json para incluir uma lista de ocupações, e elas são definidas em ordem não alfabética para garantir que nossos testes validem que as ocupações sejam classificadas alfabeticamente por getOccupations()
.
{
"byline": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/content/byline",
"name": "Jane Doe",
"occupations": ["Photographer", "Blogger", "YouTuber"]
}
}
Execute o teste e novamente nós passamos! Parece ter as ocupações organizadas funcionando!
testGetOccupations() passa
O último método a testar isEmpty()
.
Teste isEmpty()
é interessante, pois requer testes para várias condições. Revisão BylineImpl.java's isEmpty()
Devem ser ensaiadas as seguintes condições:
Para isso, precisamos criar métodos de teste, cada um testando uma condição específica e novas estruturas de recursos de modelo em BylineImplTest.json
para conduzir esses testes.
Essa verificação nos permitiu ignorar o teste de quando getName()
, getOccupations()
e getImage()
estão vazias, pois o comportamento esperado desse estado é testado por meio de isEmpty()
.
O primeiro teste testará a condição de um componente totalmente novo, que não tenha propriedades definidas.
Adicione uma nova definição de recurso a BylineImplTest.json
, atribuindo-lhe o nome semântico "empty"
{
"byline": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/content/byline",
"name": "Jane Doe",
"occupations": ["Photographer", "Blogger", "YouTuber"]
},
"empty": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/content/byline"
}
}
"empty": {...}
defina uma nova definição de recurso chamada “empty” que só tem uma jcr:primaryType
e sling:resourceType
.
Lembrar que carregamos BylineImplTest.json
em ctx
antes da execução de cada método de ensaio em @setUp
, portanto, essa nova definição de recurso está imediatamente disponível para nós em testes em /content/empty.
Atualizar testIsEmpty()
como segue, definindo o recurso atual para o novo "empty" definição de recurso mock.
@Test
public void testIsEmpty() {
ctx.currentResource("/content/empty");
Byline byline = ctx.request().adaptTo(Byline.class);
assertTrue(byline.isEmpty());
}
Execute o teste e verifique se ele foi aprovado.
Em seguida, crie um conjunto de métodos para garantir que, se qualquer um dos pontos de dados necessários (nome, ocupações ou imagem) esteja vazio, isEmpty()
retorna true.
Para cada teste, uma definição de recurso de modelo discreta é usada, atualizar BylineImplTest.json com definições de recursos adicionais para sem nome e sem ocupações.
{
"byline": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/content/byline",
"name": "Jane Doe",
"occupations": ["Photographer", "Blogger", "YouTuber"]
},
"empty": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/content/byline"
},
"without-name": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/content/byline",
"occupations": "[Photographer, Blogger, YouTuber]"
},
"without-occupations": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "wknd/components/content/byline",
"name": "Jane Doe"
}
}
Crie os seguintes métodos de teste para testar cada um desses estados.
@Test
public void testIsEmpty() {
ctx.currentResource("/content/empty");
Byline byline = ctx.request().adaptTo(Byline.class);
assertTrue(byline.isEmpty());
}
@Test
public void testIsEmpty_WithoutName() {
ctx.currentResource("/content/without-name");
Byline byline = ctx.request().adaptTo(Byline.class);
assertTrue(byline.isEmpty());
}
@Test
public void testIsEmpty_WithoutOccupations() {
ctx.currentResource("/content/without-occupations");
Byline byline = ctx.request().adaptTo(Byline.class);
assertTrue(byline.isEmpty());
}
@Test
public void testIsEmpty_WithoutImage() {
ctx.currentResource("/content/byline");
lenient().when(modelFactory.getModelFromWrappedRequest(eq(ctx.request()),
any(Resource.class),
eq(Image.class))).thenReturn(null);
Byline byline = ctx.request().adaptTo(Byline.class);
assertTrue(byline.isEmpty());
}
@Test
public void testIsEmpty_WithoutImageSrc() {
ctx.currentResource("/content/byline");
when(image.getSrc()).thenReturn("");
Byline byline = ctx.request().adaptTo(Byline.class);
assertTrue(byline.isEmpty());
}
testIsEmpty()
faz o teste em relação à definição de recurso de modelo vazio e afirma que isEmpty()
é verdadeiro.
testIsEmpty_WithoutName()
O testa uma definição de recurso de modelo que tem ocupações, mas nenhum nome.
testIsEmpty_WithoutOccupations()
O testa uma definição de recurso de modelo que tem um nome, mas nenhuma ocupação.
testIsEmpty_WithoutImage()
O testa uma definição de recurso de modelo com um nome e ocupações, mas define o modelo de Imagem para retornar a nulo. Observe que queremos substituir a variável modelFactory.getModelFromWrappedRequest(..)
comportamento definido em setUp()
para garantir que o objeto Image retornado por esta chamada seja nulo. O recurso de bordas do Mockito é rigoroso e não deseja código duplicado. Por isso, colocamos a espada com lenient
configurações para observar explicitamente que estamos substituindo o comportamento na variável setUp()
método .
testIsEmpty_WithoutImageSrc()
testa uma definição de recurso de modelo com um nome e ocupações, mas define o modelo de Imagem para retornar uma string em branco quando getSrc()
é chamado.
Por fim, escreva um teste para garantir que isEmpty() retorna false quando o componente está configurado corretamente. Para esta condição, podemos reutilizar /content/byline que representa um componente Byline totalmente configurado.
@Test
public void testIsNotEmpty() {
ctx.currentResource("/content/byline");
when(image.getSrc()).thenReturn("/content/bio.png");
Byline byline = ctx.request().adaptTo(Byline.class);
assertFalse(byline.isEmpty());
}
Agora, execute todos os testes de unidade no arquivo BylineImplTest.java e revise a saída do Relatório de teste do Java™.
Os testes de unidade são executados e precisam ser aprovados como parte da compilação maven. Isso garante que todos os testes sejam bem-sucedidos antes da implantação de um aplicativo. A execução de metas Maven, como pacote ou instalação, chama automaticamente e requer a aprovação de todos os testes de unidade no projeto.
$ mvn package
$ mvn package
Da mesma forma, se alterarmos um método de teste para falhar, a build falhará e reportará quais testes falharam e por quê.
Exibir o código concluído em GitHub ou revise e implante o código localmente na ramificação Git tutorial/unit-testing-solution
.