Expressとマングースで構築されたRESTAPIをテストしようとしています。http呼び出しにjestとsupertestを使用しています。また、私はjavascriptを使用したテストに比較的慣れていません。
作成URLをテストするとき、インスタンス化がreq.bodyオブジェクトだけを使用して呼び出されることを確認したくありませんが、モックオブジェクトとスタブ、およびいくつかのJestの違いについて多くを読んだ後、その方法がわかりません。私の最後の試みのドキュメントは次のようになります:
test('Should instantiate the model using req.body', done => {
const postMock = jest.fn();
const testPost = {
name: 'Test post',
content: 'Hello'
};
postMock.bind(Post); // <- Post is my model
// I mock the save function so it doesn't use the db at all
Post.prototype.save = jest.fn(cb => cb(null, testPost));
// Supertest call
request(app).post('/posts/')
.send(testPost)
.then(() => {
expect(postMock.mock.calls[0][0]).toEqual(testPost);
done();
})
.catch(err => {throw err});
});
また、promise拒否のテストに手動で失敗する方法を知りたいので、 Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
現状では、ルートハンドラー関数自体を分離してそれだけをテストするのではなく、より多くの統合テストを実行しています。
まず、ハンドラーを/posts/
独自のファイルに分割します(まだこれを行っていない場合)。
controllers/post-controller.js
const Post = require('./path/to/models/post')
exports.store = async (req, res) => {
const post = await new Post(req.body).save()
res.json({ data: post }
}
次に、ルートを定義した場所でハンドラーを使用します。
const express = require('express')
const app = express()
const postController = require('./path/to/controllers/post-controller')
app.post('/posts', postController.store)
この抽象化により、を分離してpostController.store
、で動作することをテストできますreq.body
。実際のデータベースにヒットしないようにマングースをモックする必要があるPost
ので、(すでに持っているコードを使用して)そのようにモックを作成できます。
path/to/models/__mocks__/post.js
const post = require('../post')
const mockedPost = jest.fn()
mockedPost.bind(Post)
const testPost = {
name: 'Test post',
content: 'Hello'
}
Post.prototype.save = jest.fn(cb => {
if (typeof cb === 'function') {
if (process.env.FORCE_FAIL === 'true') {
process.nextTick(cb(new Error(), null))
} else {
process.nextTick(cb(null, testPost))
}
} else {
return new Promise((resolve, reject) => {
if (process.env.FORCE_FAIL === 'true') {
reject(new Error())
} else {
resolve(testPost)
}
})
}
})
module.exports = mockedPost
process.env.FORCE_FAIL
何らかの理由で失敗したいかどうかのチェックに注意してください。
これで、req.body
作品を使用してそれをテストする準備が整いました。
post-controller.test.js
// Loads anything contained in `models/__mocks__` folder
jest.mock('../location/to/models')
const postController = require('../location/to/controllers/post-controller')
describe('controllers.Post', () => {
/**
* Mocked Express Request object.
*/
let req
/**
* Mocked Express Response object.
*/
let res
beforeEach(() => {
req = {
body: {}
}
res = {
data: null,
json(payload) {
this.data = JSON.stringify(payload)
}
}
})
describe('.store()', () => {
test('should create a new post', async () => {
req.body = { ... }
await postController(req, res)
expect(res.data).toBeDefined()
...
})
test('fails creating a post', () => {
process.env.FORCE_FAIL = true
req.body = { ... }
try {
await postController.store(req, res)
} catch (error) {
expect(res.data).not.toBeDefined()
...
}
})
})
})
このコードはテストされていませんが、テストに役立つことを願っています。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加