I am totally new to using Jest, especially in regards to unit tests, and I am struggling to write a test for a specific scenario.
I know that you can mock an external module like this..
jest.mock('@organisation/library', () => ({
Database: jest.fn(() => ({})),
....,
....,
}))
If you want to use an actual method from that module, you can do something like
const database = jest.requireActual('@organisation/library')
What I'm trying to do is mock only one method from the library, not the entire library itself.
Is this possible?
Let me explain the code a bit further.
We have a file called StationRepository
. This file includes a Database
method from our JS framework.
The file then calls the database and returns a value.
I want to test that database query.
Here is the test
import { DatabaseModule, Pg } from '@organisation/framework'
import { StationRepository } from './StationRepository'
import { DatabaseConfig } from '../../spec'
const DatabaseInstance = new DatabaseModule()
beforeAll(async () => {
DatabaseInstance.add('default', new Pg('default', DatabaseConfig))
jest.clearAllMocks()
})
afterAll(async () => {
const database = DatabaseInstance.get()
await database.disconnect()
})
describe('find timezone', () => {
it('can find a timezone', async () => {
const ids = [1, 2]
const expected = ['Pacific/Auckland', 'Australia/Adelaide']
const results = []
for (const id of ids) {
const timezone: string | null = await StationRepository.findTimezone(id)
results.push(timezone)
}
expect(results).toEqual(expected)
})
})
And the method in the repository
import { DatabaseFacade as Database } from '@organisation/framework'
export class StationRepository {
/**
* Find Timezone
*
* Finds the station or system timezone and returns
* will return station timezone
* if no station timezone will return system timezone
* if no system timezone null will be returned
*
* @param {number} stationId - The station id to search on
* @param {string} db - Optional - The Database connection
*
* @return string | null
*/
public static findTimezone = async (
stationId: number,
db?: string,
): Promise<string | null> => {
const query = `
SELECT
(CASE
WHEN stations.timezone IS NOT NULL
THEN stations.timezone
WHEN systems.timezone IS NOT NULL
THEN systems.timezone
END
) AS timezone
FROM
stations
INNER JOIN systems ON systems.id = stations.system_id
WHERE
stations.id = $1
`
const result = await Database.get(db).queryOne<StationTimezone | null>.(
query,
[stationId],
)
if (!result) {
return null
}
return result.timezone
}
}
Everything seems to be working well, setting up the connection from the test and all. However, it fails on the actual query Database.get()
. This is being loaded in from the framework. If I mock the entire framework, everything breaks.
So essentially, what I want to do is have the framework run normally, but only replace the DatabaseFacade
section to use the DatabaseInstance
created in the test.
Is this possible?