Nederlands

Een uitgebreide gids voor integratietesten gericht op API-testen met Supertest, inclusief setup, best practices en geavanceerde technieken voor robuuste applicatietesten.

Integratietesten: Beheers API-testen met Supertest

In de wereld van softwareontwikkeling is het cruciaal om ervoor te zorgen dat individuele componenten afzonderlijk correct functioneren (unit testing). Het is echter even belangrijk om te verifiëren dat deze componenten naadloos samenwerken. Hier komt integratietesten om de hoek kijken. Integratietesten richt zich op het valideren van de interactie tussen verschillende modules of services binnen een applicatie. Dit artikel duikt diep in integratietesten, met een specifieke focus op API-testen met Supertest, een krachtige en gebruiksvriendelijke bibliotheek voor het testen van HTTP-assertions in Node.js.

Wat is Integratietesten?

Integratietesten is een type softwaretesten waarbij individuele softwaremodules worden gecombineerd en als groep worden getest. Het doel is om defecten in de interacties tussen geïntegreerde eenheden aan het licht te brengen. In tegenstelling tot unit testing, dat zich richt op individuele componenten, verifieert integratietesten de data- en controlestroom tussen modules. Veelvoorkomende benaderingen voor integratietesten zijn:

In de context van API's omvat integratietesten het verifiëren dat verschillende API's correct samenwerken, dat de gegevens die tussen hen worden doorgegeven consistent zijn, en dat het algehele systeem functioneert zoals verwacht. Stel je bijvoorbeeld een e-commerce applicatie voor met afzonderlijke API's voor productbeheer, gebruikersauthenticatie en betalingsverwerking. Integratietesten zou ervoor zorgen dat deze API's correct communiceren, zodat gebruikers producten kunnen bekijken, veilig kunnen inloggen en aankopen kunnen voltooien.

Waarom is API-integratietesten Belangrijk?

API-integratietesten is om verschillende redenen cruciaal:

Neem een wereldwijd reisboekingsplatform. API-integratietesten is van het grootste belang om een soepele communicatie te garanderen tussen API's die vluchtreserveringen, hotelboekingen en betalingsgateways uit verschillende landen afhandelen. Het niet correct integreren van deze API's kan leiden tot onjuiste boekingen, betalingsfouten en een slechte gebruikerservaring, wat de reputatie en omzet van het platform negatief beïnvloedt.

Introductie van Supertest: Een Krachtige Tool voor API-testen

Supertest is een high-level abstractie voor het testen van HTTP-requests. Het biedt een handige en vloeiende API voor het verzenden van requests naar je applicatie en het doen van assertions op de responses. Supertest is gebouwd bovenop Node.js en is specifiek ontworpen voor het testen van Node.js HTTP-servers. Het werkt uitzonderlijk goed met populaire testframeworks zoals Jest en Mocha.

Belangrijkste Kenmerken van Supertest:

Het Opzetten van je Testomgeving

Voordat we beginnen, laten we een basis testomgeving opzetten. We gaan ervan uit dat je Node.js en npm (of yarn) hebt geïnstalleerd. We gebruiken Jest als ons testframework en Supertest voor API-testen.

  1. Maak een Node.js-project aan:
mkdir api-testing-example
cd api-testing-example
npm init -y
  1. Installeer afhankelijkheden:
npm install --save-dev jest supertest
npm install express  # Of je favoriete framework voor het maken van de API
  1. Configureer Jest: Voeg het volgende toe aan je package.json-bestand:
{
  "scripts": {
    "test": "jest"
  }
}
  1. Maak een eenvoudig API-eindpunt: Maak een bestand genaamd app.js (of vergelijkbaar) met de volgende code:
const express = require('express');
const app = express();
const port = 3000;

app.get('/hello', (req, res) => {
  res.send('Hello, World!');
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});

module.exports = app; // Exporteer voor het testen

Je Eerste Supertest-test Schrijven

Nu we onze omgeving hebben opgezet, laten we een eenvoudige Supertest-test schrijven om ons API-eindpunt te verifiëren. Maak een bestand genaamd app.test.js (of vergelijkbaar) in de root van je project:

const request = require('supertest');
const app = require('./app');

describe('GET /hello', () => {
  it('responds with 200 OK and returns "Hello, World!"', async () => {
    const response = await request(app).get('/hello');
    expect(response.statusCode).toBe(200);
    expect(response.text).toBe('Hello, World!');
  });
});

Uitleg:

Om de test uit te voeren, voer je het volgende commando uit in je terminal:

npm test

Als alles correct is ingesteld, zou je de test moeten zien slagen.

Geavanceerde Supertest-technieken

Supertest biedt een breed scala aan functies voor geavanceerd API-testen. Laten we er een paar verkennen.

1. Request Bodies Verzenden

Om gegevens in de request body te verzenden, kun je de .send()-methode gebruiken. Laten we bijvoorbeeld een eindpunt maken dat JSON-data accepteert:

app.post('/users', express.json(), (req, res) => {
  const { name, email } = req.body;
  // Simuleer het aanmaken van een gebruiker in een database
  const user = { id: Date.now(), name, email };
  res.status(201).json(user);
});

Zo kun je dit eindpunt testen met Supertest:

describe('POST /users', () => {
  it('creates a new user', async () => {
    const userData = {
      name: 'John Doe',
      email: 'john.doe@example.com',
    };

    const response = await request(app)
      .post('/users')
      .send(userData)
      .expect(201);

    expect(response.body).toHaveProperty('id');
    expect(response.body.name).toBe(userData.name);
    expect(response.body.email).toBe(userData.email);
  });
});

Uitleg:

2. Headers Instellen

Om aangepaste headers in je requests in te stellen, kun je de .set()-methode gebruiken. Dit is handig voor het instellen van authenticatietokens, content types of andere aangepaste headers.

describe('GET /protected', () => {
  it('requires authentication', async () => {
    const response = await request(app).get('/protected').expect(401);
  });

  it('returns 200 OK with a valid token', async () => {
    // Simuleer het verkrijgen van een geldig token
    const token = 'valid-token';

    const response = await request(app)
      .get('/protected')
      .set('Authorization', `Bearer ${token}`)
      .expect(200);

    expect(response.text).toBe('Protected Resource');
  });
});

Uitleg:

3. Omgaan met Cookies

Supertest kan ook omgaan met cookies. Je kunt cookies instellen met de .set('Cookie', ...)-methode, of je kunt de .cookies-eigenschap gebruiken om cookies te openen en aan te passen.

4. Testen van File Uploads

Supertest kan worden gebruikt om API-eindpunten te testen die file uploads afhandelen. Je kunt de .attach()-methode gebruiken om bestanden aan de request te koppelen.

5. Gebruik van Assertion-bibliotheken (Chai)

Hoewel de ingebouwde assertion-bibliotheek van Jest in veel gevallen volstaat, kun je ook krachtigere assertion-bibliotheken zoals Chai met Supertest gebruiken. Chai biedt een expressievere en flexibelere assertion-syntaxis. Om Chai te gebruiken, moet je het installeren:

npm install --save-dev chai

Vervolgens kun je Chai in je testbestand importeren en de assertions gebruiken:

const request = require('supertest');
const app = require('./app');
const chai = require('chai');
const expect = chai.expect;

describe('GET /hello', () => {
  it('responds with 200 OK and returns "Hello, World!"', async () => {
    const response = await request(app).get('/hello');
    expect(response.statusCode).to.equal(200);
    expect(response.text).to.equal('Hello, World!');
  });
});

Let op: Mogelijk moet je Jest configureren om correct met Chai te werken. Dit houdt vaak in dat je een setup-bestand toevoegt dat Chai importeert en configureert om te werken met de globale expect van Jest.

6. Hergebruiken van Agents

Voor tests die een specifieke omgeving vereisen (bijv. authenticatie), is het vaak voordelig om een Supertest-agent te hergebruiken. Dit voorkomt overbodige setup-code in elke testcase.

describe('Authenticated API Tests', () => {
  let agent;

  beforeAll(() => {
    agent = request.agent(app); // Maak een persistente agent
    // Simuleer authenticatie
    return agent
      .post('/login')
      .send({ username: 'testuser', password: 'password123' });
  });

  it('can access a protected resource', async () => {
    const response = await agent.get('/protected').expect(200);
    expect(response.text).toBe('Protected Resource');
  });

  it('can perform other actions that require authentication', async () => {
    // Voer hier andere geauthenticeerde acties uit
  });
});

In dit voorbeeld maken we een Supertest-agent aan in de beforeAll-hook en authenticeren we de agent. Opeenvolgende tests binnen het describe-blok kunnen deze geauthenticeerde agent vervolgens hergebruiken zonder voor elke test opnieuw te hoeven authenticeren.

Best Practices voor API-integratietesten met Supertest

Om effectieve API-integratietesten te garanderen, overweeg de volgende best practices:

Veelvoorkomende Fouten om te Vermijden

Conclusie

API-integratietesten is een essentieel onderdeel van het softwareontwikkelingsproces. Door Supertest te gebruiken, kun je eenvoudig uitgebreide en betrouwbare API-integratietests schrijven die helpen de kwaliteit en stabiliteit van je applicatie te waarborgen. Onthoud dat je je moet richten op het testen van end-to-end workflows, het gebruik van realistische data, het isoleren van je tests en het automatiseren van je testproces. Door deze best practices te volgen, kun je het risico op integratieproblemen aanzienlijk verminderen en een robuuster en betrouwbaarder product leveren.

Aangezien API's moderne applicaties en microservices-architecturen blijven aansturen, zal het belang van robuust API-testen, en met name integratietesten, alleen maar toenemen. Supertest biedt een krachtige en toegankelijke toolset voor ontwikkelaars wereldwijd om de betrouwbaarheid en kwaliteit van hun API-interacties te waarborgen.