Descomplicando: testes unitários

Quem sou?

Motivação

Descomplicando os testes

    // Função para formatar a string para maiúsculo
    function toUpper(message: string) {
        return message.toUpperCase()
    }
    test("should return message formated", () => {
        const message = toUpper("anyMessage")
        expect(message).toBe("ANYMESSAGE")
    })

Caso real de um teste

interface HttpRequest {
  name: string
  email: string
  password: string
}

interface HttpResponse {
  statusCode: number
  body: any
}

class CreateUserController {
    async handle(request: HttpRequest) {
      if(!request.name || !request.email || !request.password) 
          return {
            statusCode: 400
            body: new Error("send all required fields")
          }
          
      return {
        statusCode: 200,
        body: "ok"
      }
    }
}
  test("it should return 400 if no name is provided", async () => {
    const createUserController = new CreateUserController()
    const response = await createUserController.handle({
        name: '',
        email: 'anyEmail@mail.com',
        password: 'anyPassword'
    })
    expect(response).toEqual({
      statusCode: 400,
      body: new Error("send all required fields")
    })
  })
  
  test("it should return 400 if no email is provided", async () => {
    const createUserController = new CreateUserController()
    const response = await createUserController.handle({
        name: 'anyName',
        email: '',
        password: 'anyPassword'
    })
    expect(response).toEqual({
      statusCode: 400,
      body: new Error("send all required fields")
    })
  })
  
  test("it should return 400 if no password is provided", async () => {
    const createUserController = new CreateUserController()
    const response = await createUserController.handle({
        name: 'anyName',
        email: 'anyEmail@mail.com',
        password: ''
    })
    
    expect(response).toEqual({
      statusCode: 400,
      body: new Error("send all required fields")
    })
  })
  
  test("it should return 200 valid data is provided", async () => {
    const createUserController = new CreateUserController()
    const response = await createUserController.handle({
        name: 'anyName',
        email: 'anyEmail@mail.com',
        password: 'anyPassword'
    })
    
    expect(response).toEqual({
      statusCode: 200,
      body: "ok"
    })
  })

Conclusão

Links

Fala Carlos Vinicius! Muito massa seu post! Na mesma pegada de desenvolvimento testável e escrevendo uma arquitetura desacoplada, publiquei esse artigo sobre a utilização de um ORM no contexto testável e independente. No meu desenvolvimento guiado por testes, gosto muito de utilizar o factory pattern para o gerenciamento de entradas da minha função/classe. EX: Nesse mesmo contexto de teste de uma classe controller, gosto de configurar meu teste da seguinte maneira:

import { CreateUserController } from "./controller";

const makeHttpRequest = (props?: Partial<HttpRequest>): HttpRequest => ({
  name: "any_name",
  email: "any_email",
  password: "any_password",
  ...props,
});

test("it should return 400 if no name is provided", async () => {
  const createUserController = new CreateUserController();
  const request = makeHttpRequest({ name: undefined });
  const response = await createUserController.handle(request);
  expect(response).toEqual({
    statusCode: 400,
    body: new Error("send all required fields"),
  });

  test("it should return 200 valid data is provided", async () => {
    const createUserController = new CreateUserController();
    const request = makeHttpRequest();
    const response = await createUserController.handle(request);

    expect(response).toEqual({
      statusCode: 200,
      body: "ok",
    });
  });
});

No exemplo acima, a função makeHttpRequest monta a minha requisição com todos os parâmetros válidos, e se eu quiser sobrescrever algum parâmetro, eu passo na chamada da função, como estou fazendo no primeiro teste. Isso me ajuda a manter o teste mais legível e com menos repetições.

Da mesma maneira, no segundo teste, eu não preciso passar nenhum parâmetro, pois a função makeHttpRequest já monta a requisição com todos os parâmetros válidos.

Espero que ajude! Abraço!

Muito interessante, realmente deve ajudar muito na questão de não repetir os paramêtros a serem enviados. Vou começar a utilizar nas minhas aplicações também, obrigado pela dica hehe. Abração

Eu sofro na hora dos testes unitarios kkk

kkkk, testes unitários são bem difíceis quando não estrutura bem o código. mas isso são dores que aprendemos a lidar com a prática, vamos vendo o que funciona e o que não funciona e isso ao longo do tempo vai se moldando e se tornando muito mais simples. então não desista, testes são muuuito importantes para uma aplicação que queira ter um bom tempo de vida pela facilidade de manutenção que esses testes irão trazer ao longo do tempo.

eu realmente gostei do artigo e se puder criar un artigo sobre as outras camadas... principalmente a de servicos, ficaria feliz em ler :)

obrigada pelo conteudo

Com certeza, trarei mais detalhes sobre as outras camadas em posts futuros

Deixa eu te perguntar, você tem alguma dica para fazer testes envolvendo mockar APIs de terceiros e comunicação com Redis?

Porque eu tenho um caso que preciso em um o nestjs que tem muitas etapas, muitas trechos código que precisam de todo um contexto no Redis para conseguir chegar no estado válido que eu quero testar.

Olá Carlos, preciso e quero começar certo, estou no inicio de front e quero entender mais e saber implementar testes unitários nos meus códigos, por onde eu começo? Documentação de como fazer? Valeu o post.

Olá, com certeza posso trazer algum post sobre testes no frontend. mas logo adianto que se você estiver muito no comecinho, ainda não começou a estudar react ou alguma lib de front mais moderna, ainda não está na hora de se preocupar com testes. A necessidade de usar testes unitários vem com o tempo, a dor de criar algo novo e quebrar o que já estava funcionando ou apenas bugs pequenos que aparecem do nd, os testes ajudariam a evitar mas quando esse periodo chegar, você vai enxergar com clareza a importancia dos testes. Mas estarei trazendo um conteúdo de testes unitários no ReactJS. a pegada é muito parecida com esse que trouxe mas com alguns detalhes um pouquinho mais chato. Forte abraço e espero que esse conteúdo e os próximos auxilie você a construir sua carreira!!
Obrigado cara pelas palavras e entendi a dica sim valeu.