Svenska

En omfattande guide till integrationstestning med fokus på API-testning med Supertest, som täcker installation, bästa praxis och avancerade tekniker för robust applikationstestning.

Integrationstestning: Bemästra API-testning med Supertest

Inom mjukvaruutveckling är det avgörande att säkerställa att enskilda komponenter fungerar korrekt isolerat (enhetstestning). Men det är lika viktigt att verifiera att dessa komponenter fungerar sömlöst tillsammans. Det är här integrationstestning kommer in i bilden. Integrationstestning fokuserar på att validera interaktionen mellan olika moduler eller tjänster i en applikation. Den här artikeln dyker djupt ner i integrationstestning, med särskilt fokus på API-testning med Supertest, ett kraftfullt och användarvänligt bibliotek för att testa HTTP-assertions i Node.js.

Vad är integrationstestning?

Integrationstestning är en typ av mjukvarutestning som kombinerar enskilda mjukvarumoduler och testar dem som en grupp. Syftet är att avslöja defekter i interaktionerna mellan integrerade enheter. Till skillnad från enhetstestning, som fokuserar på enskilda komponenter, verifierar integrationstestning dataflödet och kontrollflödet mellan moduler. Vanliga metoder för integrationstestning inkluderar:

I samband med API:er innebär integrationstestning att verifiera att olika API:er fungerar korrekt tillsammans, att data som skickas mellan dem är konsekvent och att systemet som helhet fungerar som förväntat. Föreställ dig till exempel en e-handelsapplikation med separata API:er för produkthantering, användarautentisering och betalningshantering. Integrationstestning skulle säkerställa att dessa API:er kommunicerar korrekt, vilket gör det möjligt för användare att bläddra bland produkter, logga in säkert och slutföra köp.

Varför är API-integrationstestning viktigt?

API-integrationstestning är avgörande av flera anledningar:

Tänk på en global plattform för resebokningar. API-integrationstestning är av yttersta vikt för att säkerställa smidig kommunikation mellan API:er som hanterar flygreservationer, hotellbokningar och betalningsgateways från olika länder. Om dessa API:er inte integreras korrekt kan det leda till felaktiga bokningar, betalningsmisslyckanden och en dålig användarupplevelse, vilket negativt påverkar plattformens rykte och intäkter.

Introduktion till Supertest: Ett kraftfullt verktyg för API-testning

Supertest är en abstraktion på hög nivå för att testa HTTP-anrop. Det erbjuder ett bekvämt och flytande API för att skicka förfrågningar till din applikation och göra assertions på svaren. Supertest är byggt ovanpå Node.js och är specifikt utformat för att testa Node.js HTTP-servrar. Det fungerar exceptionellt bra med populära testramverk som Jest och Mocha.

Nyckelfunktioner i Supertest:

Konfigurera din testmiljö

Innan vi börjar, låt oss sätta upp en grundläggande testmiljö. Vi antar att du har Node.js och npm (eller yarn) installerat. Vi kommer att använda Jest som vårt testramverk och Supertest för API-testning.

  1. Skapa ett Node.js-projekt:
mkdir api-testing-example
cd api-testing-example
npm init -y
  1. Installera beroenden:
npm install --save-dev jest supertest
npm install express  # Eller ditt föredragna ramverk för att skapa API:et
  1. Konfigurera Jest: Lägg till följande i din package.json-fil:
{
  "scripts": {
    "test": "jest"
  }
}
  1. Skapa en enkel API-endpoint: Skapa en fil med namnet app.js (eller liknande) med följande kod:
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; // Exportera för testning

Skriva ditt första Supertest-test

Nu när vi har vår miljö konfigurerad, låt oss skriva ett enkelt Supertest-test för att verifiera vår API-endpoint. Skapa en fil med namnet app.test.js (eller liknande) i roten av ditt projekt:

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!');
  });
});

Förklaring:

För att köra testet, kör följande kommando i din terminal:

npm test

Om allt är korrekt konfigurerat bör du se att testet passerar.

Avancerade Supertest-tekniker

Supertest erbjuder ett brett utbud av funktioner för avancerad API-testning. Låt oss utforska några av dem.

1. Skicka data i anropets body

För att skicka data i anropets body (request body) kan du använda metoden .send(). Låt oss till exempel skapa en endpoint som accepterar JSON-data:

app.post('/users', express.json(), (req, res) => {
  const { name, email } = req.body;
  // Simulera att skapa en användare i en databas
  const user = { id: Date.now(), name, email };
  res.status(201).json(user);
});

Så här kan du testa denna endpoint med 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);
  });
});

Förklaring:

2. Sätta headers

För att sätta anpassade headers i dina anrop kan du använda metoden .set(). Detta är användbart för att sätta autentiseringstokens, content types eller andra anpassade 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 () => {
    // Simulera att hämta en giltig token
    const token = 'valid-token';

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

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

Förklaring:

3. Hantera cookies

Supertest kan också hantera cookies. Du kan sätta cookies med metoden .set('Cookie', ...), eller så kan du använda egenskapen .cookies för att komma åt och ändra cookies.

4. Testa filuppladdningar

Supertest kan användas för att testa API-endpoints som hanterar filuppladdningar. Du kan använda metoden .attach() för att bifoga filer till anropet.

5. Använda assertions-bibliotek (Chai)

Även om Jests inbyggda assertions-bibliotek är tillräckligt i många fall, kan du också använda kraftfullare assertions-bibliotek som Chai med Supertest. Chai erbjuder en mer uttrycksfull och flexibel syntax för assertions. För att använda Chai måste du installera det:

npm install --save-dev chai

Sedan kan du importera Chai i din testfil och använda dess assertions:

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!');
  });
});

Observera: Du kan behöva konfigurera Jest för att fungera korrekt med Chai. Detta innebär ofta att man lägger till en setup-fil som importerar Chai och konfigurerar det att fungera med Jests globala expect.

6. Återanvända agenter

För tester som kräver att en specifik miljö sätts upp (t.ex. autentisering) är det ofta fördelaktigt att återanvända en Supertest-agent. Detta undviker redundant setup-kod i varje testfall.

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

  beforeAll(() => {
    agent = request.agent(app); // Skapa en beständig agent
    // Simulera autentisering
    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 () => {
    // Utför andra autentiserade åtgärder här
  });
});

I detta exempel skapar vi en Supertest-agent i beforeAll-hooken och autentiserar agenten. Efterföljande tester inom describe-blocket kan sedan återanvända denna autentiserade agent utan att behöva autentisera på nytt för varje test.

Bästa praxis för API-integrationstestning med Supertest

För att säkerställa effektiv API-integrationstestning, överväg följande bästa praxis:

Vanliga misstag att undvika

Slutsats

API-integrationstestning är en väsentlig del av mjukvaruutvecklingsprocessen. Genom att använda Supertest kan du enkelt skriva omfattande och tillförlitliga API-integrationstester som hjälper till att säkerställa kvaliteten och stabiliteten i din applikation. Kom ihåg att fokusera på att testa end-to-end-arbetsflöden, använda realistisk data, isolera dina tester och automatisera din testprocess. Genom att följa dessa bästa praxis kan du avsevärt minska risken för integrationsproblem och leverera en mer robust och tillförlitlig produkt.

I takt med att API:er fortsätter att driva moderna applikationer och mikrotjänstarkitekturer, kommer vikten av robust API-testning, och särskilt integrationstestning, bara att fortsätta växa. Supertest erbjuder en kraftfull och tillgänglig verktygslåda för utvecklare över hela världen för att säkerställa tillförlitligheten och kvaliteten på deras API-interaktioner.