Jest 및 Supertest 를 통해 Express 애플리케이션에 대한 테스트 추가

아마존에서 내 책 보기https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
지금 http://jauyeung.net/subscribe/에 내 이메일 목록을 구독하십시오.
자동화 테스트는 현대 응용 프로그램에 많은 활동 부품이 있기 때문에 우리가 작성한 응용 프로그램에 매우 중요하다.
이 글은 데이터베이스JestSuperTest와 상호작용하는 Express 프로그램을 테스트하기 위해 프로그램을 작성하는 방법을 소개할 것이다.

테스트할 프로그램 만들기
빈 폴더를 만들고 다음 명령을 실행하여 기본 답안package.json 파일을 만듭니다.
npm init -y
그런 다음 다음 다음 프로그램을 실행하여 패키지를 설치합니다.
npm i express sqlite3 body-parser
그런 다음 애플리케이션을 위한 app.js 파일을 만들고 작성했습니다.
const express = require('express');  
const sqlite3 = require('sqlite3').verbose();  
const bodyParser = require('body-parser');  
const app = express();  
const port = process.env.NODE_ENV === 'test' ? 3001 : 3000;  
let db;  
if (process.env.NODE_ENV === 'test') {  
    db = new sqlite3.Database(':memory:');  
}  
else {  
    db = new sqlite3.Database('db.sqlite');  
}

db.serialize(() => {  
    db.run('CREATE TABLE IF NOT EXISTS persons (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)');  
});

app.use(bodyParser.json());  
app.get('/', (req, res) => {  
    db.serialize(() => {  
        db.all('SELECT * FROM persons', [], (err, rows) => {  
            res.json(rows);  
        });  
    })  
})

app.post('/', (req, res) => {  
    const { name, age } = req.body;  
    db.serialize(() => {  
        const stmt = db.prepare('INSERT INTO persons (name, age) VALUES (?, ?)');  
        stmt.run(name, age);  
        stmt.finalize();  
        res.json(req.body);  
    })  
})

app.put('/:id', (req, res) => {  
    const { name, age } = req.body;  
    const { id } = req.params;  
    db.serialize(() => {  
        const stmt = db.prepare('UPDATE persons SET name = ?, age = ? WHERE id = ?');  
        stmt.run(name, age, id);  
        stmt.finalize();  
        res.json(req.body);  
    })  
})

app.delete('/:id', (req, res) => {  
    const { id } = req.params;  
    db.serialize(() => {  
        const stmt = db.prepare('DELETE FROM persons WHERE id = ?');  
        stmt.run(id);  
        stmt.finalize();  
        res.json(req.body);  
    })  
})

const server = app.listen(port);  
module.exports = { app, server };
위의 코드에는 우리가 테스트할 응용 프로그램이 있다.
EMC 는 다음과 같이 애플리케이션을 테스트하기 쉽게 만듭니다.
const port = process.env.NODE_ENV === 'test' ? 3001 : 3000;  
let db;  
if (process.env.NODE_ENV === 'test') {  
    db = new sqlite3.Database(':memory:');  
}  
else {  
    db = new sqlite3.Database('db.sqlite');  
}
따라서 process.env.NODE_ENV'test'로 설정하여 프로그램이 감청하는 포트가 비테스트 환경에서 실행될 때와 다르게 할 수 있습니다.
우리는 'test' 환경을 사용하여 테스트를 실행할 것이다.
마찬가지로, 우리는 우리의 응용 프로그램이 단원 테스트를 실행할 때 단원 테스트를 실행하지 않을 때와 다른 데이터베이스를 사용하기를 희망한다.
이것이 바로 우리가 가지고 있는 이유이다.
let db;  
if (process.env.NODE_ENV === 'test') {  
    db = new sqlite3.Database(':memory:');  
}  
else {  
    db = new sqlite3.Database('db.sqlite');  
}
우리는 응용 프로그램이 'test' 환경에서 실행될 때 데이터베이스 파일이 아닌 SQLite의 메모리 데이터베이스를 사용하기를 원한다고 지정했다.

작성 테스트

코드 초기화
테스트 가능한 응용 프로그램이 있으면 우리는 그것에 테스트를 추가할 수 있다.
Jest 테스트 실행 프로그램과 SuperTest를 사용하여 테스트 중에 라우팅을 요청합니다.Jest 및 SuperTest를 추가하려면 다음을 수행합니다.
npm i jest supertest
그리고 우리는 app.test.js 위의 app.js 파일과 같은 폴더에 추가할 것입니다.app.test.js에서 먼저 다음과 같은 내용을 쓰겠습니다.
const { app } = require('./app');  
const sqlite3 = require('sqlite3').verbose();  
const request = require('supertest');  
const db = new sqlite3.Database(':memory:');
beforeAll(() => {  
    process.env.NODE_ENV = 'test';  
})
위 코드에는 Dellapp.js의 Express 애플리케이션이 포함되어 있습니다.그리고 SQLite3 및 SuperTest 패키지도 포함됩니다.
그런 다음 다음과 같은 방법으로 메모리 데이터베이스에 연결합니다.
const db = new sqlite3.Database(':memory:');
다음 명령을 실행하여 모든 테스트를 'test' 환경에서 실행하도록 설정합니다.
beforeAll(() => {  
    process.env.NODE_ENV = 'test';  
})
이렇게 하면 테스트마다 포트3001app.js에 지정된 메모리 데이터베이스를 사용할 수 있습니다.
우리의 테스트가 독립적으로 실행되고 일치된 결과를 얻기 위해서, 우리는 매번 데이터베이스를 정리하고 새로운 데이터를 삽입해야 한다.
이를 위해 각 테스트에서 호출되는 함수를 만들었습니다.
const seedDb = db => {  
    db.run('CREATE TABLE IF NOT EXISTS persons (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)');  
    db.run('DELETE FROM persons');  
    const stmt = db.prepare('INSERT INTO persons (name, age) VALUES (?, ?)');  
    stmt.run('Jane', 1);  
    stmt.finalize();  
}
persons표가 존재하지 않으면 위의 코드가 이 표를 만들고 그 중의 모든 내용을 삭제합니다.
그리고 우리는 시작 데이터를 얻기 위해 그 안에 새로운 값을 삽입했다.

테스트 추가
초기화 코드가 완성되면 우리는 테스트를 작성할 수 있다.

요청 테스트 가져오기
우선, 우리는 테스트를 작성하여 GET 요청을 통해 데이터베이스에서 기존 피드 데이터를 가져옵니다.
우리는 글을 써서 이 점을 해냈다.
test('get persons', () => {  
    db.serialize(async () => {  
        seedDb(db);  
        const res = await request(app).get('/');  
        const response = [  
            { name: 'Jane', id: 1, age: 1 }  
        ]  
        expect(res.status).toBe(200);  
        expect(res.body).toEqual(response);  
    })  
});
우리는 모든 내용을 db.serialize의 리셋에 넣을 것이기 때문에 조회는 순서대로 실행될 것이다.
우선, 우리는 seedDb를 호출했다. 우리는 위에서 테이블을 만들고, 데이터베이스를 지우고, 새로운 데이터를 추가했다.
그리고 우리는 서면으로 GET 요청을 호출했다.
await request(app).get('/');
이로써 res 대상을 얻었고 그 호응은 이미 약속에서 해결되었다.request(app) 요청할 수 있도록 Express 애플리케이션을 시작합니다.
다음으로는 response의 정확성을 살펴보겠습니다.
const response = [  
  { name: 'Jane', id: 1, age: 1 }  
]
그리고 우리는 대답을 검사해서 우리가 예상한 결과를 얻었는지 확인한다.
expect(res.status).toBe(200);  
expect(res.body).toEqual(response);
toBe 방법 검사는 얕은 것과 같고 toEqual 검사는 깊은 것과 같다.그래서 우리는 toEqual를 사용하여 전체 대상 구조가 같은지 검사한다.res.status 서버에서 되돌아오는 상태 코드를 검사하고res.body 응답 주체가 있다.

요청 후 테스트
다음은 POST에 테스트를 추가해 달라고 요청합니다.그것은 GET 테스트를 요청하는 것과 유사하다.
다음 코드를 작성합니다.
test('add person', () => {  
    db.serialize(async () => {  
        seedDb(db);  
        await request(app)  
            .post('/')  
            .send({ name: 'Joe', age: 2 }); 
        const res = await request(app).get('/');  
        const response = [  
            { name: 'Jane', id: 1, age: 1 },  
            { name: 'Joe', id: 2, age: 2 }  
        ]  
        expect(res.status).toBe(200);  
        expect(res.body).toEqual(response);  
    })  
});
먼저 다음과 같은 방법으로 데이터베이스를 재설정합니다.
seedDb(db);
POST 요청 시
await request(app)  
  .post('/')  
  .send({ name: 'Joe', age: 2 });
이것은 메모리 데이터베이스에 새 항목을 삽입할 것입니다.
마지막으로, 정확성을 검사하기 위해서, 우리는 GET 요청을 보냈습니다. 첫 번째 테스트에서처럼, 두 항목이 되돌아왔는지 확인하십시오.
const res = await request(app).get('/');  
const response = [  
  { name: 'Jane', id: 1, age: 1 },  
  { name: 'Joe', id: 2, age: 2 }  
]  
expect(res.status).toBe(200);  
expect(res.body).toEqual(response);

테스트 배치 및 제거PUT 요청의 테스트는 POST 요청과 유사합니다.데이터베이스를 재설정하고 유효 로드를 사용하여 PUT 요청을 실행한 다음 GET 요청을 실행하여 다음과 같이 반환된 데이터를 가져옵니다.
test('update person', () => {  
    db.serialize(async () => {  
        seedDb(db);  
        await request(app)  
            .put('/1')  
            .send({ name: 'Joe', age: 2 }); 
        const res = await request(app).get('/');  
        const response = [  
            { name: 'Jane', id: 1, age: 1 }  
        ]  
        expect(res.status).toBe(200);  
        expect(res.body).toEqual(response);  
    })  
});
그리고 우리는 PUT 요청으로 DELETE 요청을 교체하고 DELETE 요청을 테스트할 수 있다.
test('delete person', () => {  
    db.serialize(async () => {  
        seedDb(db);  
        const res = await request(app).delete('/1');  
        const response = [];  
        expect(res.status).toBe(200);  
        expect(res.body).toEqual(response);  
    })  
});

실행 테스트
테스트를 실행하기 위해 다음을 scripts 섹션에 추가합니다.
"test": "jest --forceExit"
테스트 실행 후에 Jest가 존재하도록 --forceExit 옵션을 추가해야 합니다.SuperTest를 사용하는 Jest 테스트가 올바르게 종료되지 않은 문제에 대한 해결책이 없습니다.
그런 다음 테스트를 실행하기 위해 다음 프로그램을 실행합니다.
npm test
우리는 다음과 같이 해야 한다.
PASS  ./app.test.js  
  √ get persons (11ms)  
  √ add person (2ms)  
  √ update person (2ms)  
  √ delete person (6ms)Test Suites: 1 passed, 1 total  
Tests:       4 passed, 4 total  
Snapshots:   0 total  
Time:        2.559s  
Ran all test suites.  
Force exiting Jest: Have you considered using `--detectOpenHandles` to detect async operations that kept running after all tests finished?
우리가 몇 번이나 테스트를 실행하든지 간에, 우리는 같은 결과를 얻어야 한다. 왜냐하면 우리는 데이터베이스를 리셋하고, 모든 데이터베이스 조회를 순서대로 실행하기 때문이다.
또한 우리는 테스트에서 다른 환경과 다른 데이터베이스와 포트를 사용했기 때문에 데이터는 깨끗해야 한다.

결론
Jest 테스트 실행 프로그램을 사용하여 실행되는 테스트를 추가할 수 있습니다.이 점을 하려면, 우리는 반드시 다른 포트와 데이터베이스를 가지고 테스트를 실행해야 한다.그리고 만약에 테이블이 존재하지 않는다면 우리는 그것들을 만들고 모든 데이터를 지우고 피드 데이터를 추가하여 모든 테스트가 같은 데이터베이스 구조와 내용을 가지도록 할 것이다.
SuperTest를 통해 Express 애플리케이션을 자동으로 실행하고 요청할 수 있습니다.그리고 우리는 출력을 검사할 수 있다.

좋은 웹페이지 즐겨찾기