Reputation: 409
General question before. When I use jest.mock() can I only mock the whole module? Or also exported functions, constants. In my app.js, I use for example const fileSystem = require('fs'). I'm trying to test the app, which has a method where it reads a file with fs. Do I have now to mock the 'fs' module in my test or load the app.js and mock then the constant where fs is loaded?
Here is my code:
const express = require('express')
const dataFilePath = '../shoppinglist/data.json'
const fileSystem = require('fs')
let data
module.exports = {app, listener, getNewestId, getSmsFormatedShoppingList, readUpdatedData,
dataFilePath}
app.get(baseUrl, (req, res) => {
let finishedState
readUpdatedData()
if(isDataEmpty()){
return res.status(200).send([])
}
if(req.query.isFinished){
finishedState = req.query.isFinished === 'true'
}
const listsWithoutItems = data.data.map(({ items, ...rest }) => rest)
const filteredList = (finishedState === true || finishedState === false) ? sortShoppingListByFinished(listsWithoutItems, finishedState) : listsWithoutItems
if(filteredList.length === 0){
res.statusCode = 204
res.send()
}
// adjust later, this is just used for tests
res.setHeader('Content-Type', 'application/json')
data.data = filteredList
res.json(data)
res.status(200).send()
})
function readUpdatedData(){
let rawData = fileSystem.readFileSync(dataFilePath)
data = JSON.parse(rawData)
console.log(data)
console.log('-------------------------')
}
Now I like to test, if the api call is successful and the data which are read is correct. For this I tried to mock the data.json, but when the test runs, then fileSystem.readFileSync('../shoppinglist/data.json') is always undefined. So I guess when it loads the app, it ignores somehow my mocked data for ../shoppinglist/data.json
describe('Get for all Lists with entries', () => {
it('should return a list with 2 entries without items', async () => {
jest.mock('../shoppinglist/data.json', () => ({
"data" : [
{
"id": 0,
"name": "filled shopping list",
"location": "lidl",
"targetDate": "22.03.1986",
"priority": 1,
"isFinished": false,
"items": [{"count":1, "name": "vodka" }, {"count":1, "name": "vodka" }
]
}, {
"id": 1,
"name": "filled shopping list2",
"location": "lidl2",
"targetDate": "22.03.1986",
"priority": 1,
"isFinished": false,
"items": [{"count":1, "name": "vodka" }, {"count":1, "name": "vodka" }
]
}
]}))
const {app} = require(appPath)
let res
res = await request(app)
.get(baseUrl)
expect(res.statusCode).toEqual(200)
expect(res.body.data).toHaveLength(2)
expect(res.body[0]).toEqual(expect.not.objectContaining({"items": ["vodka"]}))
})
})
I've tried also to mock the fs in my test, but I guess it doesn't work like this
NEW EDIT AFTER TRY
I've tried now this in the test:
const fs = require( 'fs')
jest.mock('fs')
describe('Get for all Lists with entries', () => {
it('should return a list with 2 entries without items', async () => {
fs.writeFileSync.mockClear();
fs.readFileSync.mockReturnValue('X')
const {app} = require(appPath)
let res
res = await request(app)
.get(baseUrl)
expect(res.statusCode).toEqual(200)
expect(res.body.data).toHaveLength(2)
expect(res.body[0]).toEqual(expect.not.objectContaining({"items":
["vodka"]}))
})
})
But still, when app.js is called with
const {app} = require(appPath)
let res
res = await request(app)
.get(baseUrl)
the method readUpdateData has always at rawData undefined, like the mock is never returend.
function readUpdatedData(){
let rawData = fileSystem.readFileSync(dataFilePath)
data = JSON.parse(rawData)
module.exports = data
console.log(data)
console.log('-------------------------')
}
Upvotes: 0
Views: 1179
Reputation: 409
I've found now a solution
const mockReadFile = jest.spyOn(fs, 'readFileSync')
mockReadFile.mockImplementation(() => JSON.stringify({
"data" : [
{
"id": 0,
"name": "filled shopping list",
"location": "lidl",
"targetDate": "22.03.1986",
"priority": 1,
"isFinished": false,
"items": [{"count":1, "name": "vodka" }, {"count":1, "name": "vodka" }
]
}, {
"id": 1,
"name": "filled shopping list2",
"location": "lidl2",
"targetDate": "22.03.1986",
"priority": 1,
"isFinished": false,
"items": [{"count":1, "name": "vodka" }, {"count":1, "name":
"vodka" }
]
}
]}))
With this, the data is correctly read from the mock
Upvotes: 0