Reputation: 13486
I have a very simple little utility function xml2JSON
as follows
import { promisify } from 'util'
import { parseString } from 'xml2js'
const xml2js = promisify(parseString)
const xmlToJSON = async xml => xml2js(xml)
export default xmlToJSON
I am trying to test it with Jest, mocking out the stuff I don't need to care about
import * as util from 'util'
import * as xml2js from 'xml2js'
import xmlToJSON from './xmlToJSON'
jest.mock('util')
jest.mock('xml2js')
describe('xmlToJSON', () => {
const promisifiedParseString = jest.fn()
util.promisify = jest.fn(() => promisifiedParseString)
const js = { some: 'result' }
const xml = '<some>result</some>'
let result
beforeAll(async () => {
promisifiedParseString.mockResolvedValue(js)
result = await xmlToJSON(xml)
})
it('promisified the original parseString', () => {
expect(util.promisify).toHaveBeenCalledWith(xml2js.parseString)
})
it('called the promisified parseString with the xml', () => {
expect(promisifiedParseString).toHaveBeenCalledWith(xml)
})
it('returned the expected result', () => {
expect(result).toEqual(js)
})
})
But I am getting the error
TypeError: xml2js is not a function
4 | const xml2js = promisify(parseString)
5 |
> 6 | const xmlToJSON = async xml => xml2js(xml)
| ^
7 |
8 | export default xmlToJSON
9 |
What am I doing wrong?
Based on suggestion below I have tried changing the order of the imports:
import * as util from 'util'
import * as xml2js from 'xml2js'
jest.mock('util')
jest.mock('xml2js')
const promisifiedParseString = jest.fn()
util.promisify = jest.fn(() => promisifiedParseString)
import xmlToJSON from './xmlToJSON'
describe('xmlToJSON', () => {
const js = { some: 'result' }
const xml = '<some>result</some>'
let result
beforeAll(async () => {
promisifiedParseString.mockResolvedValue(js)
result = await xmlToJSON(xml)
})
it('promisified the original parseString', () => {
expect(util.promisify).toHaveBeenCalledWith(xml2js.parseString)
})
it('called the promisified parseString with the xml', () => {
expect(promisifiedParseString).toHaveBeenCalledWith(xml)
})
it('returned the expected result', () => {
expect(result).toEqual(js)
})
})
but it made no difference.
Upvotes: 4
Views: 3938
Reputation: 41
I know this is old, but you need to also change
import xmlToJSON from './xmlToJSON'
to
const xmlToJSON = require('./xmlToJSON');
because imports get hoisted to the top of the script, and requires do not.
Upvotes: 0
Reputation: 9116
You need to change util.promisify
behaviour before you import the file which is using it.
So the order should be something like:
util.promisify = jest.fn(() => promisifiedParseString)
import xmlToJSON from './xmlToJSON'
Upvotes: 1