тестовый узел, экспресс-конечная точка и заглушка стороннего API-вызова

У меня есть такое экспресс-приложение:

сервер.js

const postsController = require('./controllers/posts_controller.js')
module.exports = app = express()
app.get('posts', postsController.index)

posts_controller.js

const post = require('./post')()

module.exports = {
  index: (req, res) => {
    post.getAll().then((posts) => {
      res.status(200).send(posts)
    }, (error) => {
      res.status(400).send('text')
    })
  }
}

post.js

module.exports = () => {
  const thirdPartyApi = require('third_party_api')
  return {
    get: () => {
      // do some stuff
      return thirdPartyApi.get().then((resp) => {
        // do some more stuff
        return Promise.resolve(resp)
      })
    }
  }
}

спец/posts_controller_spec.js

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

describe('GET /posts', () => {
  it('should return a collection of posts', () => {
    request(app)
     .get('/posts')
     .end((_err, resp) => {
       expect(resp.status).toEqual(200)
     })
  })
})

Моя цель здесь — заглушить thirdPartyApi.get(). Я попытался с proxyquire, добавив эту строку в posts_controller_spec:

proxyquire('../posts_controller', {third_party_api: {
  get: () => { console.log('stubbed out get method'); }
})

Это не работает, потому что файл server.js — это файл, для которого снова требуется файл Third_Party_API.


Я мог бы сделать что-то подобное, чтобы протестировать контроллер:

const postsController = proxyquire('../posts_controller', {third_party_api: {
  get: () => { console.log('stubbed out get method'); }
})


postsController.index(req, res)

Эта вторая стратегия не кажется правильной, потому что теперь мне нужно заглушить req и res, а теперь я обхожу фактический экземпляр app.

Есть ли простой способ сделать это с помощью proxyquire или как-то иначе?


person dylanjha    schedule 15.07.2016    source источник


Ответы (1)


Я понял, что происходит, proxyquire тут не при чем.

файл post.js экспортирует функцию, поэтому, когда posts_controller.js требует() файл post.js, он выполняет функцию, а требование для third_party_api оценивается снова, и заглушка стирается.

Это сценарий runtimeGlobal, описанный здесь: https://www.npmjs.com/package/proxyquire#globally-override-require-during-module-runtime

Решение состоит в том, чтобы исправить post.js, чтобы он не экспортировал функцию:

const thirdPartyApi = require('third_party_api')
return {
  get: () => {
    // do some stuff
    return thirdPartyApi.get().then((resp) => {
      // do some more stuff
      return Promise.resolve(resp)
    })
  }
}

Теперь, пока это происходит до инициализации приложения,

proxyquire('../posts_controller', {third_party_api: {
  get: () => { console.log('stubbed out get method'); }
}) 

Затем модуль Third_Party_API, который требуется внутри пост-контроллера, оценивается во время загрузки и кэшируется, как и ожидалось.

person dylanjha    schedule 15.07.2016