jbrumwell / mock-knex

A mock knex adapter for simulating a database during testing
MIT License
239 stars 71 forks source link

Step not working with multiple same method #128

Closed restuwahyu13 closed 3 years ago

restuwahyu13 commented 3 years ago

Step not working with multiple same method, my problem is, if I give value to step 2 with undefined, I get response back company id is not exist and I give value to step 2 with object I get response back Car protection name already exist, it should be if I give value to step 1 with object and I give value to step two with undefined, It will go to next step to 3, but this goes back to the first step and I get response back company id is not exist, how to fix it this issue ?

My Controller

import { checkSchema } from 'express-validator'
import { ApiRequest, ApiResponse } from '../../interface/common'
import { CarProtection, Company } from '../../interface/model'
import db from '../../lib/db'

export async function createCarProtection(req: ApiRequest, res: ApiResponse): Promise<any> {
    try {
        const getCompanyId = await db<Company>('company').select().where({ id: req.body.companyId }).first()

        if (getCompanyId === undefined) {
            throw {
                status: 'ERROR',
                httpStatus: 404,
                error: 'CREATE_CAR_PROTECTION',
                message: `company ${req.body.companyId} id is not exist`,
                code: '7MBGOYN6'
            }
        }

        // check car protection name already exist or not
        const checkCarProtectionExist = await db<CarProtection>('car_protection').select().where({ name: req.body.name }).first()

        if (checkCarProtectionExist !== undefined) {
            throw {
                status: 'ERROR',
                httpStatus: 409,
                error: 'CREATE_CAR_PROTECTION',
                message: `Car protection name ${req.body.name} already exist`,
                code: 'SYV3J01R'
            }
        }

        try {
            // create new car protection
            const createCarProtection = await db<CarProtection>('car_protection').insert({
                name: req.body.name,
                description: req.body.description,
                price: parseFloat(req.body.price),
                companyId: getCompanyId?.id || '',
                createdAt: new Date()
            })

            if (createCarProtection.length < 1) {
                throw {
                    status: 'ERROR',
                    httpStatus: 403,
                    error: 'CREATE_CAR_PROTECTION',
                    message: 'Create car protection failed',
                    code: 'P7I3V0OE'
                }
            }

            const json = {
                status: 'Ok',
                message: 'Create car protection successfully'
            }

            res.status(201).json(json)
            return json
        } catch (err) {
            throw {
                status: 'ERROR',
                httpStatus: 500,
                error: 'CREATE_CAR_PROTECTION',
                message: err.message,
                code: 'F96VTYS8'
            }
        }
    } catch (err) {
        console.error(err)
        const json = {
            status: err.status || 'ERROR',
            httpStatus: err.httpStatus || 400,
            message: err.message || 'Create car protection failure',
            code: err.code || '7S5AD1ZP'
        }
        res.status(err.httpStatus).json(json)
        return json
    }
}

My Test

import 'mocha'
import bcrypt from 'bcrypt'
import chai from 'chai'
import knexMock from 'mock-knex'
import httpMock from 'node-mocks-http'
import db from '../../lib/db'
import { createCarProtection } from '../../controllers/car_protection/createCarProtection'
import { mockData } from '../mock-data/mock.data'

let req, res, tracker, hashPassword, confirmHashPassword

describe('[Unit Testing] - Auth Controller - Agtran Server API V1', function () {
    beforeEach(function () {
        // create model mock
        tracker = knexMock.getTracker()
        tracker.install()
        knexMock.mock(db)

        // create express request and response mock
        req = httpMock.createRequest()
        res = httpMock.createResponse()
    })

    afterEach(function () {
        // reset mock after every each test finish
        tracker.uninstall()
        knexMock.unmock(db)
    })

    describe('Car Protection Created', function () {
        it('[POST] - /car-protection/create - Should be create car protection failed', async function () {
            req.body.name = 'sinarmas finance'
            req.body.description = mockData.carProtection.description
            req.body.price = mockData.carProtection.price
            req.body.companyId = mockData.carProtection.companyId

            tracker.once('query', (query, step) => {
                if (query.method !== undefined && step === 1) chai.expect(query.method).to.equal('first')
                query.response(mockData.carProtection)
            })

            tracker.once('query', (query, step) => {
                if (query.method !== undefined && step === 2) chai.expect(query.method).to.equal('first')
                query.response(undefined)
            })

            tracker.on('query', (query) => {
                if (query.method !== undefined) chai.expect(query.method).to.equal('insert')
                query.response([])
            })

            await createCarProtection(req, res)
            const data = res._getJSONData()

            chai.expect(res._isEndCalled()).to.be.true
            chai.expect(res._getStatusCode()).to.be.equal(403)
            chai.expect(res._getHeaders()).to.be.contain({ 'content-type': 'application/json' })
            chai.expect(data.message).to.be.equal(`Create car protection failed`)
        })
    })
})
restuwahyu13 commented 3 years ago

Solved my issue with this

tracker.on('query', (query, step) => {
    return [
        () => {
            if (query.method !== undefined && step === 1) chai.expect(query.method).to.equal('first')
            query.response(mockData.carProtection)
        },
        () => {
            if (query.method !== undefined && step === 2) chai.expect(query.method).to.equal('first')
            query.response(mockData.carProtection)
        },
        () => {
            if (query.method !== undefined && step === 3) chai.expect(query.method).to.equal('insert')
            query.response([mockData.carProtection])
        }
    ][step - 1]()
})