Do you want to request a feature or report a bug?
report a bug
What is the current behavior?
_repl.it demo: https://repl.it/FuQO/0_
let MyMock = jest.fn();
MyMock.mockImplementation(() => ({
name: 'test',
}));
describe('some tests', () => {
it('run the instances check', () => {
let newMock = new MyMock();
expect(MyMock.mock.instances.length).toBe(1);
expect(MyMock.mock.instances[0]).toBe(newMock);
});
});
```
- Expected
+ Received
-Object {
- "name": "test",
-}
+mockConstructor {}
**What is the expected behavior?** (Copied from API docs)
```javascript
// had a `name` property whose value was set to 'test'
expect(someMockFunction.mock.instances[0].name).toEqual('test'); // success
More Info
This API is documented but tests only run with empty functions. I have written tests here which are failing due to this bug.
https://github.com/facebook/jest/compare/master...vibhavsinha:master
Please provide your exact Jest configuration and mention your Jest, node, yarn/npm version and operating system.
This is expected. Mocking works by subclassing things in Jest.
@cpojer can you please point to any code example that shows how to do this?
this seems to work https://github.com/facebook/jest/issues/663
Here's my work around for manually mocking ES6 classes.
It also work with functions. It does not align with Jest documentation
Note that it is a function()
that I use for mockImplementation()
let MyMock = jest.fn();
MyMock.mockImplementation(function() {
this.name = 'test'
this.foo = jest.fn(() => {
return 'bar'
})
});
describe('some tests', () => {
it('run the instances check', () => {
let newMock = new MyMock();
newMock.foo()
expect(MyMock.mock.instances.length).toBe(1);
expect(MyMock.mock.instances[0]).toBe(newMock);
expect(MyMock.mock.instances[0].foo).toHaveBeenCalled()
});
});
If anyone's curious, here's what I ended up using in my TypeScript project:
Let's say that I want to test this function:
export async function list(DomainName: string, next?: string): Promise<MyModelListResponse> {
const simpledb = new SimpleDB();
const params: SimpleDB.SelectRequest = {
SelectExpression: `select * from \`${DomainName}\``,
...next ? { NextToken: next } : {}
};
console.log(`Querying SimpleDB: ${JSON.stringify(params, null, 2)}`);
const resp = await simpledb.select(params).promise();
return {
results: resp.Items.map(
item => item.Attributes.reduce(
(obj, attr) => Object.assign(obj, {[attr.Name]: attr.Value}),
{}
) as MyModel
),
nextToken: resp.NextToken
};
}
My test:
import { SimpleDB } from 'aws-sdk';
import * as MyDbInterface from './db';
jest.mock('aws-sdk');
const MockSimpleDB = SimpleDB as any as jest.MockInstance<SimpleDB>;
// Create mock object that simulates the response of `new SimpleDB().someMethod(args).promise()`
const mockAwsMethodPromiseObject = (prototype: {[method: string]: any}): {[key: string]: jest.Mock} =>
Object.assign({},
...Object.entries(prototype).map(([method, response]) => ({
[method]: jest.fn(() => ({
promise: jest.fn(() => response)
}))
}))
)
;
describe('DB list', () => {
it('should list returned models', async () => {
const response: SimpleDB.SelectResult = {
Items: [{Name: 'foo', Attributes: [{Name: 'id', Value: 'foo'}]}]
};
const mock = mockAwsMethodPromiseObject({select: Promise.resolve(response)});
MockSimpleDB.mockImplementation(() => mock);
const models = [{'id': 'foo'}];
expect(
await MyDbInterface.list('testDomain')
).toEqual({
nextToken: undefined,
results: models
});
expect(MockSimpleDB).toHaveBeenCalledTimes(1); // Instantiated
expect(mock.select).toHaveBeenCalledTimes(1);
expect(mock.select).toHaveBeenCalledWith({SelectExpression: "select * from `testDomain`"});
});
});
I'm definitely not an expert regarding testing, Jest, or TypeScript, however this seems to work for me.
Hi guys,
If you would like to pass typescript class as mocked class, this is my typescript version of @tinyroy 's workaround.
The mock (./__mocks__/PluginManager.ts)
class PluginManagerMockImpl {
run = jest.fn(() => {
console.log("I am mocked");
})
}
export const PluginManager = jest.fn().mockImplementation(PluginManagerMockImpl as any);
The test (./TestClass.test.ts)):
test("will run", async () => {
const pluginManager = new (PluginManager as any)()
pluginManager.run();
const pluginManagerMock = mocked(PluginManager);
const runMocked = mocked(pluginManagerMock.mock.instances[0].run);
expect(runMocked).toBeCalledTimes(1);
});
Most helpful comment
Here's my work around for manually mocking ES6 classes.
It also work with functions. It does not align with Jest documentation
Note that it is a
function()
that I use formockImplementation()