When I try to use mockito-ts
to mock the return value of member functions on instances of mocked objects, I get that the member function is not a function.
TypeError: Cannot read properties of null (reading 'methodStubCollection')
When I ran this in the larger project I am working on, I had a different message indicating a similar issue. Basically, mockObject.mockMethod is not a function
.
this question and others emphasize that the instance
call is critical, and I think I've done that right. But I still see issues.
Here is the minimal reproducible code example:
package.json:
{
"name": "dwf_backend",
"version": "1.0.0",
"description": "Server for DrawWithFriends app",
"main": "index.js",
"scripts": {
"test": "jest --coverage",
"dev": "concurrently \"npx tsc --watch\" \"nodemon -q dist/server.js\"",
"start": "ts-node src/index.ts"
},
"author": "TJ",
"license": "ISC",
"devDependencies": {
"@types/jest": "^29.5.1",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"ts-mockito": "^2.6.1"
}
}
test/mockito_test.test.ts:
import { mock, instance, anything, when } from 'ts-mockito'
class B {
public doTheThing(str: string): number {
return str.length;
}
}
class A {
private readonly b: B;
constructor(b: B) {
this.b = b;
}
public doTheMainThing() {
this.b.doTheThing('strrr');
}
}
describe('test cases', () => {
it('passes', () => {
});
it('mocks', () => {
const mockedB: B = mock(B);
const a = new A(instance(mockedB));
a.doTheMainThing();
});
it('controls the mocked method', () => {
const mockedB: B = mock(B);
const instanceB: B = instance(mockedB);
console.log(`instanceB is: ${JSON.stringify(instanceB)}`);
when(instanceB.doTheThing(anything())).thenReturn(4);
const a = new A(instanceB);
a.doTheMainThing();
});
});
run with npm run test
From Stubbing method calls doc, we should pass the mocked object returned by the mock
function rather than the instance object returned by the instance
function to the when
function to stub method and its return value.
It should be:
const mockedB: B = mock(B);
const instanceB: B = instance(mockedB);
when(mockedB.doTheThing(anything())).thenReturn(4);
NOT
const mockedB: B = mock(B);
const instanceB: B = instance(mockedB);
when(instanceB.doTheThing(anything())).thenReturn(4);
An working example:
import { mock, instance, anything, when } from 'ts-mockito'
class B {
public doTheThing(str: string): number {
return str.length;
}
}
class A {
private readonly b: B;
constructor(b: B) {
this.b = b;
}
public doTheMainThing() {
return this.b.doTheThing('strrr');
}
}
describe('test cases', () => {
it('controls the mocked method', () => {
const mockedB: B = mock(B);
const instanceB: B = instance(mockedB);
when(mockedB.doTheThing(anything())).thenReturn(4);
const a = new A(instanceB);
const actual = a.doTheMainThing();
expect(actual).toBe(4);
});
});
Test result:
PASS stackoverflow/76133872/index.test.ts
test cases
✓ controls the mocked method (2 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.665 s, estimated 1 s