Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample unit test for model #141

Open
1change opened this issue Jul 28, 2018 · 5 comments
Open

Sample unit test for model #141

1change opened this issue Jul 28, 2018 · 5 comments

Comments

@1change
Copy link
Contributor

1change commented Jul 28, 2018

Is your feature request related to a problem? Please describe.
I'm new to Hapi & mongoose and trying to setup unit test for some model I define with Jest, but having found no references on google how to do it properly, so running into some sort of trial and error to make it work.

Describe the solution you'd like
One sample unit test where you could run CRUD or call method in a model

Describe alternatives you've considered

const Mongoose = require('mongoose')
const RestHapi = require('rest-hapi')
const Config = require('../../config')
const restHapiConfig = Config.get('/restHapiConfig')

// process.env.NODE_ENV = 'development'
const path = require('path')

// we require the handlers directly, so we can test the "Lib" functions in isolation
const Manifest = require('../../config/manifest.conf');
const Glue = require('glue');

describe('unit tests - programs', () => {
  let models

  beforeAll(async (done) => {

    RestHapi.config = restHapiConfig
    RestHapi.config.absoluteModelPath = true
    RestHapi.config.modelPath = path.join(__dirname, '../../server/models')

    models = await RestHapi.generateModels(Mongoose)


    const composeOptions = {
      relativeTo: path.join(__dirname, '../../')
    }

    const manifest = Manifest.get('/')
    const server = await Glue.compose(manifest, composeOptions)

    await server.start()

    done()
  })

  it('should return a report body', async (done) => {

    const logger = RestHapi.getLogger('test').bind()
    const UserData = Mongoose.model('user_program')
    let userData = await RestHapi.list(UserData, {$limit: 1}, logger)
    let reportBody = await models.program.getEvaluationSummary(userData, logger)
    console.log(reportBody)
    expect(reportBody).toBeDefined();
    done()
  });

  afterAll((done) => {
    process.exit(0)
    done()
  });

});

Additional context
Above is my trial and it works but could have been better, I guess having a setup.js and not calling generateModels and server.start every time.

@1change
Copy link
Contributor Author

1change commented Jul 28, 2018

When I tried to setup a globalSetup (instead of BeforeAll). It caused an issue like below. It seems mongoose don't store the models in globalSetup

MissingSchemaError: Schema hasn't been registered for model "user_program".
Use mongoose.model(name, schema)

      39 | 
      40 |     const logger = RestHapi.getLogger('test').bind()
    > 41 |     const UserData = Mongoose.model('user_program')
      42 |     const Program = Mongoose.model('program')
      43 |     let userData = await RestHapi.list(UserData, {$limit: 1}, logger)
      44 |     let reportBody = await Program.getEvaluationSummary(userData, logger)
      
      at new MissingSchemaError (node_modules/mongoose/lib/error/missingSchema.js:20:11)
      at Mongoose.Object.<anonymous>.Mongoose.model (node_modules/mongoose/lib/index.js:336:13)
      at Object.it (test/unit/program.model.test.js:41:31)

@JKHeadley
Copy link
Owner

Hi @1change, sorry for the late response, life has been busy lately.

Glad you got a working example. For your 'globalSetup', are you trying to run an external setup script (like the setup.js you mentioned)? I believe after you register the rest-hapi plugin you need to pass the Mongoose instance back to your test script instead of using a separate require('mongoose'). So maybe something like

const setup = require('setup.js')

...

const Mongoose = await setup()

Also, for the code you posted, since you are using beforeAll it should not have to call server.start and generateModels every time, correct?

@1change
Copy link
Contributor Author

1change commented Aug 20, 2018

Hi @JKHeadley, thx for taking the time. Yes beforeAll won't call server every time but in every testspec, so having a globalSetup would help.

@sanzoghenzo
Copy link

sanzoghenzo commented May 27, 2019

I went through some trial & errors, too, and I think I came to a decent solution.
require('mongoose') returns a singleton, so if you call if after the server creation, you get the cached mongoose instance.
The following example doesn't start the server (only initializes it), since I was interested in testing some methods declared in Schema.static without calling API endpoints.
I also make sure to close mongoose connection in order to avoid the "Jest did not exit one second after the test run has completed." message.

'use strict'

describe('Sample Test Suite', () => {
  let server, mongoose, sampleCollection
  let createdIds = []

  beforeAll(async (done) => {
    const Glue = require('glue')
    const Manifest = require('../../config/manifest.conf')
    const composeOptions = { relativeTo: '../../' }
    const manifest = Manifest.get('/')
    server = await Glue.compose(manifest, composeOptions)
    // getting mongoose singleton
    mongoose = require('mongoose')
    sampleCollection = mongoose.model('sampleCollection')
    done()
  })

  beforeEach(async (done) => {
    // populate collections
    const sampleData = [...] 
    const newObjs = await sampleCollection.insertMany(pois)
    createdIds = newObjs.map(o => o._id)
    done()
  })

  test('sample test', async (done) => {
    // write you test here...
    done()
  })

  afterEach((done) => {
      if (createdIds.length) {
        sampleCollection.deleteMany({ _id: { $in: createdIds } })
      }
      done()
  })

  afterAll((done) => {
      mongoose.connection.close()
      done()
  })
})

this can be useful too.

@JKHeadley
Copy link
Owner

@sanzoghenzo very nice! Yes getting things in the right order can be a bit tricky. Thanks for sharing your solution!

As a side note, if you find spinning up a MongoDB instance too slow or cumbersome, you can using mongodb-memory-server. See this comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants