2017-08-20 13 views
2

Ich versuche eine REST-API mit Express und Mungo zu testen, verwende ich Jest und Supertest für die http-Aufrufe; Ich bin auch relativ neu beim Testen mit Javascript.Jest Test Mungo-Modell Instanziierung

Beim Testen einer Erstellungsurl sollte ich nicht sicherstellen, dass die Instantiierung nur mit dem Objekt req.body aufgerufen wird, aber ich bin mir nicht sicher, wie das geht, nachdem ich viel über Unterschiede zwischen Mock-Objekten und Stubs gelesen habe einige der Jest Dokumentation mein letzter Versuch sieht wie folgt aus:

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

}); 

auch ich würde gerne wissen, wie man manuell den Test auf dem Versprechen Ablehnung scheitern, so dass es wirft nicht die Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

Antwort

4

wie steht, führen Sie eher einen Integrationstest durch, als die Route-Handler-Funktion selbst zu isolieren und nur zu testen beim.

Zuerst würde ich den Handler für /posts/ zu einer eigenen Datei wegbrechen (vorausgesetzt, Sie dies nicht bereits getan haben):

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 } 
} 

Next einfach den Handler verwenden, wo immer Sie Ihre Routen definiert :

const express = require('express') 
const app = express() 
const postController = require('./path/to/controllers/post-controller') 

app.post('/posts', postController.store) 

mit dieser Abstraktion können wir nun unsere postController.store und Test isolieren, dass es mitfunktioniert. Jetzt, da wir Mungo verspotten benötigen eine aktuelle Datenbank zu vermeiden, schlagen, können Sie eine verspottete Post wie so erstellen (den Code, die Sie bereits haben):

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 

Hinweis Check für process.env.FORCE_FAIL wenn für aus welchem ​​Grund auch immer, Sie wollten es versäumen.

Jetzt sind wir bereit, die req.body Werke zu testen, ob mit:

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() 

     ... 
     } 
    }) 

    }) 
}) 

Dieser Code nicht getestet, aber ich hoffe, dass es in Ihrer Prüfung hilft.