Teste unitário de tecnologia de teste de software - método de teste do estilo do engenheiro (2)

Como escrever testes unitários?

Introdução ao JUnit

Basicamente, toda linguagem e estrutura possui boas estruturas e ferramentas de teste de unidade, como JUnit do Java, ScalaTest do Scala, unittest do Python, Jest do JavaScript e assim por diante. Os exemplos acima são baseados em JUnit, apresentaremos brevemente o JUnit abaixo.

Cada método anotado @Test no JUnit é um teste. @Ignore pode ignorar um teste. @Before, @BeforeClass, @After, @AfterClass podem inserir algumas operações comuns antes e depois da execução do teste, como inicialização e liberação de recursos, etc.

Além de assertEquals, JUnit também oferece suporte a muitos outros métodos assert. Por exemplo assertNull, assertArrayEquals, assertThrows, assertTimeout, etc. Além disso, você também pode usar uma biblioteca assert de terceiros, como Assert ou AssertJ do Spring.

Além de testar a lógica de código comum, o JUnit também pode realizar testes de exceção e testes de tempo. O teste de exceção serve para testar se um determinado trecho de código deve lançar uma exceção especificada, e o teste de tempo serve para testar se o tempo de execução do código está dentro de um determinado intervalo.

Também é possível agrupar testes. Por exemplo, pode ser dividido em contractTest, mockTest e unitTest, e o teste de um determinado grupo pode ser especificado por parâmetros.

Não vou apresentar muito aqui, se você quiser saber mais sobre JUnit, pode acessar o tutorial JUnit da Geek Academy e outros materiais. As funções básicas de outras estruturas de testes unitários são semelhantes.

Usar teste duplo

Em um teste de unidade restrito, testamos apenas a própria unidade. Mesmo se escrevermos um teste de unidade generalizado, ele ainda pode depender de outros módulos, como métodos de outras classes, chamadas de serviço de terceiros ou consultas de banco de dados, etc., impossibilitando testarmos muito o sistema ou módulo em teste. convenientemente. Então precisamos usar o teste Double.

Se você estudar com atenção, o teste Double é dividido em vários tipos, como Dummies, Fakes e assim por diante. Mas acho que só precisamos esclarecer duas categorias, ou seja, Stub e Mock.

Esboço

Stubs são objetos que contêm dados predefinidos e são retornados ao chamador durante o teste. Stub é frequentemente usado em cenários onde não queremos retornar dados reais ou causar outros efeitos colaterais.

O Stub Jar gerado pelo nosso teste de contrato e que pode ser executado através do stubrunner Spring Cloud é um Stub. Podemos permitir que o Stub retorne dados falsos predefinidos e então podemos confiar nesses dados em testes de unidade para testar o código. Por exemplo, podemos deixar o usuário consultar o Stub para retornar o usuário autenticado e o usuário não autenticado de acordo com o ID do usuário no parâmetro, e então podemos testar a lógica de processamento do chamador nesses dois casos.

É claro que o Stub pode não ser um serviço remoto, mas sim outra classe. Por isso, costumamos dizer que precisamos programar na interface, porque dessa forma podemos facilmente criar uma implementação Stub da interface para substituir a classe específica.

classe pública StubNameService implementa NameService {

public String get(String userId) {

return ““Nome de usuário simulado””;

}

}

classe pública UserServiceTest {

// UserService depende de NameService e chamará seu método get

@Injetar

serviço de usuário privado serviço de usuário;

@Teste

public void quandoUserIdIsProvided_thenRetrievedNameIsCorrect() {

userService.setNameService(novo StubNameService());

String testName = userService.getUserName(““SomeId””);

Assert.assertEquals(““Nome de usuário simulado””, testName);

}

}

No entanto, é muito problemático implementar muitos stubs desta forma. Agora não precisamos criar stubs sozinhos, porque existem várias ferramentas simuladas.

Zombar

Mocks referem-se a objetos que podem registrar suas informações de chamada. Nas asserções de teste, podemos verificar se os Mocks são chamados conforme o esperado.

A diferença entre Mock e Stub é que o Stub fornece apenas alguns dados, não realiza verificação ou apenas faz alguma verificação com base no estado; o Mock também pode realizar verificação com base no comportamento de chamada, além de fazer o que o Stub faz. Por exemplo, Mock pode verificar se a interface Mock é chamada exatamente duas vezes e se os parâmetros da chamada são os valores esperados.

A ferramenta Mock mais comumente usada em Java é o Mockito. Vejamos um exemplo simples, o seguinte UserService depende do NameService. Quando testamos UserService, queremos isolar NameService, para que possamos criar um Mock NameService e injetá-lo em UserService (no Spring, só precisamos usar duas anotações @Mock e @InjectMocks para completá-lo)

classe pública UserServiceTest {

@InjectMocks

serviço de usuário privado serviço de usuário;

@Zombar

nameService privado nameService;

@Teste

public void quandoUserIdIsProvided_thenRetrievedNameIsCorrect() {

Mockito.when(nameService.getUserName(““SomeId””)).thenReturn(““Nome de usuário simulado””);

String testName = userService.getUserName(““SomeId””);

Assert.assertEquals(““Nome de usuário simulado””, testName);

Mockito.verify(nameService).getUserName(““SomeId””);

}

}

Observe que a última linha acima verifica se o getUserName do nameService é chamado com o parâmetro ""SomeId"". Para obter mais informações sobre o Mockito, consulte a documentação do Mockito (

http://static.javadoc.io/org.mockito/mockito-core/2.9.0/org/mockito/Mockito.html)。

teste de contrato

O teste de contrato irá gerar um stub para cada serviço, que pode ser usado para testes de unidade/integração do chamador. Por exemplo, precisamos testar a operação de reserva do serviço de reservas, e a operação de reserva ligará para o serviço ao usuário para verificar algumas informações básicas do usuário, como se o médico é credenciado ou não.

Portanto, podemos permitir que o Stub do contrato retorne dados do usuário em diferentes estados, passando diferentes IDs de usuário, verificando assim diferentes procedimentos de processamento. Por exemplo, um caso de teste para um fluxo de compromisso normal pode ter esta aparência.

@RunWith(SpringJUnit4ClassRunner.class)

@SpringBootTest@AutoConfigureStubRunner(repositoryRoot=““http://<nexus_root>””,

ids = {"“com.xingren.service:user-client-stubs:1.0.0:stubs:6565"”})public class BookingTest {

// BookingService chamará o atendimento ao usuário e realizará diferentes processamentos após obter o status de autenticação do médico

@Injetar

serviço de reserva privado bookingService;

@Teste

public void testBooking() {

Formulário BookingForm = novo BookingForm(

1, // médicoId

1 // agendaId

1001); // pacienteId

BookVO res = bookingService.book(formulário);

assertTrue(res.id > 0);

assertTrue(res.payStatus == PayStatus.UN_PAY);

}

}

Observe que a anotação AutoConfigureStubRunner acima serve para definir e iniciar o Stub de serviço do usuário. É claro que, ao testar, precisamos definir o baseUrl da interface de chamada de serviço como http://localhost:6565. Para obter mais informações sobre testes de contrato, consulte o artigo Explorando testes de integração em um ambiente de microsserviços.

TDD

Simplificando, Desenvolvimento Orientado a Testes ou TDD. O rato canhoto escreveu um artigo dizendo que o TDD não é tão bonito quanto parece, então citei diretamente sua introdução.

Seu processo de desenvolvimento começa a partir do caso de teste de requisitos funcionais, primeiro adicione um caso de teste, depois execute todos os casos de teste para ver se há algum problema, então realize a função a ser testada pelo caso de teste e, em seguida, execute o caso de teste para ver se algum caso falha, refatore o código e repita as etapas acima.

Na verdade, o processo estrito de TDD não é muito prático, e o próprio mouse da orelha esquerda também é crítico. No entanto, para módulos com definições de interface claras, ainda é benéfico escrever primeiro os testes unitários e depois escrever o código de implementação. Porque o objetivo é claro e você pode obter feedback imediato.

Fonte do artigo: Os direitos autorais da rede pertencem ao autor original

O conteúdo acima não tem fins comerciais, caso envolva questões de propriedade intelectual, entre em contato com o editor, trataremos do assunto imediatamente

Acho que você gosta

Origin blog.csdn.net/xuezhangmen/article/details/132421937
Recomendado
Clasificación