Native Test Runner: Mocking packages that are exported as classes
Details
I'm trying to write mocks for a class that gets initialised in the file I am testing.
Please see the code example below for a detailed example of the problem. This problem often arises when trying to mock 3rd party packages (eg AWS-SDK) that export there APIs as a class that must be initialised.
Coming from Jest where mocking classes like this is very easy, I feel like I am missing something fundamental in how to use the node test runner.
Any help greatly appreciated!
Node.js version
v20.5.0
Example code
Below there are three 'files'. The Class I wish to mock, a file that creates an instance of the class, and the test file.
ClassToMock.js
class ClassToMock {
constructor() {
this.foo = 'bar'
}
doSomething = () => {
return this.foo;
}
}
export { ClassToMock }
fileToTest.js
import { ClassToMock } from './ClassToMock.js'
const functionToTest = () => {
const instance = new ClassToMock();
return instance.doSomething();
}
export { functionToTest }
fileToTest.test.js
import { test, mock } from 'node:test'
import assert from 'node:assert'
import { ClassToMock } from './ClassToMock.js
import { functionToTest } from './fileToTest.js
// mocking a method of the class
mock.method(ClassToMock, 'doSomething', () => 'Hello World')
test('test method mock', () => {
const result = functionToTest()
assert.strictEqual(result, 'Hello World') // AssertionError Expected: 'Hello World' Actual: 'bar'
})
// mocking the entire class
mock.fn(ClassToMock, () => {
return {
doSomething: () => 'Bye world'
}
})
test('test instance mock', () => {
const result = functionToTest()
assert.strictEqual(result, 'Bye World') // AssertionError. Expected: 'Bye World' Actual: 'bar'
})
Operating system
macOS
Scope
Native Test Runner
Module and version
Not applicable.
cc @nodejs/testing
Untested, but I think you want this:
// mocking a method of the class
mock.method(ClassToMock, 'doSomething', () => 'Hello World')
to be this:
// mocking a method of the class
mock.method(ClassToMock.prototype, 'doSomething', () => 'Hello World')
You can see more mocking examples in https://github.com/nodejs/node/blob/main/test/parallel/test-runner-mocking.js.
Thanks a lot for this @cjihrig Are there plans to add these examples to the docs https://nodejs.org/api/test.html?
There are no plans that I'm aware of. Documentation PRs are always welcome, although I don't know if it makes sense to document every possibility.
I tried using prototype mentioned above, but got the following error:
TypeError [ERR_INVALID_ARG_VALUE]: The argument 'methodName' must be a method. Received undefined
any other suggestions? @cjihrig
@0618 I have no clue what your code looks like so it's difficult to provide suggestions.
I tried using
prototypementioned above, but got the following error:TypeError [ERR_INVALID_ARG_VALUE]: The argument 'methodName' must be a method. Received undefined
any other suggestions? @cjihrig
hey i just deal with similar issue, i think is because the method declared inside your class in an arrow function, maybe can change from
test = () => {} into function test(){}
It seems there has been no activity on this issue for a while, and it is being closed in 30 days. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.
It seems there has been no activity on this issue for a while, and it is being closed. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.