Pinia - How to mock a specific action to test a store - pinia

Using pinia, I am not able to test what seems to be a simple scenario.
Store
const useStore = defineStore('store', () => {
const id = ref('id');
const forceId = ref('forceId');
function shouldReturnForceId() {
return false;
}
function getId() {
if (shouldReturnForceId()) {
return forceId.value;
}
return id.value;
}
return {
id,
forceId,
shouldReturnForceId,
getId,
};
});
Helper
const createTestStore = (stubActions: boolean) => {
const pinia = createTestingPinia({
stubActions,
});
setActivePinia(pinia);
const store = useStore();
return store;
};
Test
describe('Pinia Test', () => {
describe('getId', () => {
// DOES NOT WORK - stubAction to false and mocking shouldReturnForceId
it('should return forceId if shouldReturnForceId is true', () => {
const store = createTestStore(false);
store.shouldReturnForceId = jest.fn(() => true);
expect(store.getId()).toEqual('forceId');
});
// DOES NOT WORK - stubAction to true and mocking shouldReturnForceId
it('should return forceId if shouldReturnForceId is true', () => {
const store = createTestStore(true);
store.shouldReturnForceId = jest.fn(() => true);
expect(store.getId()).toEqual('forceId');
});
// WORKS
it('should return id if shouldReturnForceId is false', () => {
const store = createTestStore(false);
expect(store.getId()).toEqual('id');
});
});
});
Question
How is it possible to test a store by only mocking one action among several?
Reading the documentation I get that we can stubActions: true, which will mock all actions, but this is not what I need.

Related

Mocked zustand module with jest.mock gives typeError _zustand.default is not a function

My mock.
jest.mock("zustand", async () => {
const originalModule = await jest.requireActual("zustand");
const create = (createState) => {
const store = originalModule((set) => {
const state = createState(set);
return {
...state,
count: 5,
};
});
return store;
};
return { __esModule: true, default: create };
});
when I run test I got TypeError: (0 , _zustand.default) is not a function. This happens in my store file when it tries to create store.

Jest testing - cannot clear mocks

I have this tests in my nextjs app:
jest.mock('axios');
describe('Contacts', () => {
afterEach(() => {
axios.get.mockClear();
});
it('first test', async () => {
axios.get.mockImplementation((url: string) => {
if (url.includes('?page=1')) {
return Promise.resolve(ContactsFirstPageResponse);
} else {
return Promise.resolve(ContactsSecondPageResponse);
}
});
// ...
});
it('second test', async () => {
axios.get.mockImplementation(() => Promise.resolve(ContactsEmptyResponse));
// ...
});
});
First test passed, but second received response from ContactsFirstPageResponse
In addition I added auto clearing mocks on jest config:
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig');
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest-setup.js'],
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths),
resetMocks: true,
restoreMocks: true,
};
module.exports = createJestConfig(customJestConfig);
Please for help.

How to spy on properties returned from mocked file

Using Jest, I would like to mock one of my dependencies, but I would like to spy on the properties that mock is returning. For example, something like:
const mockGet = jest.fn(() => {});
const mockPost = jest.fn(() => {});
const mockDel = jest.fn(() => {});
jest.mock('../../services/MyService', () => {
return {
mockGet,
mockPost,
mockDel
};
});
// ...
describe('MyService', () => {
it('should do something', () => {
myService.doThis();
expect(mockGet).toHaveBeenCalled();
});
});
The problem is this gives an error jest.mock() is not allowed to reference any out-of-scope variables.
The only way I can get it to work so far is by defining the mocks inside the call to jest.mock:
jest.mock('../../services/MyService', () => {
return {
mockGet: jest.fn(() => {}),
mockPost: jest.fn(() => {}),
mockDel: jest.fn(() => {})
};
});
But then how do I access the properties to see if they were called?
Here is the solution:
Service.ts:
class Service {
public get() {
return 'real data';
}
public post() {}
public del() {}
public doThis() {
console.log('real do this');
return this.get();
}
}
export { Service };
Service.spec.ts:
import { Service } from './service';
const service = new Service();
// console.log(service);
jest.mock('./service.ts', () => {
const originalModule = jest.requireActual('./service.ts');
const { Service: OriginalService } = originalModule;
const ServiceMocked = {
...OriginalService.prototype,
get: jest.fn(),
post: jest.fn(),
del: jest.fn()
};
return {
Service: jest.fn(() => ServiceMocked)
};
});
describe('Service', () => {
it('should do something', () => {
service.get = jest.fn().mockReturnValueOnce('mocked data');
const actualValue = service.doThis();
expect(actualValue).toBe('mocked data');
expect(service.get).toHaveBeenCalled();
});
});
Unit test result:
PASS src/stackoverflow/57172774/service.spec.ts
Service
✓ should do something (11ms)
console.log src/stackoverflow/57172774/service.ts:6
real do this
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.336s, estimated 3s

Node.js Express.js: mock request object for unit-test purpose

I have a method that check if request query string has some params:
checkMandatoryQueryParams (mandatoryQueryParams: String[], req: Request): void {
let result = true;
mandatoryQueryParams.forEach((element, idx) => {
if (!req.query.hasOwnProperty(element)) {
result = false;
}
});
return result;
}
in unit-testing i need to mock the request for test it, eg:
describe('Utils', () => {
it('checkMandatoryQueryParams', () => {
const req: Request = new Request(); // pseudo-code
req.query = "?foo=test&bar=test"; // pseudo-code
expect( checkMandatoryQueryParams(['foo', 'bar'], req) ).toEqual(true);
});
});
how can i mock the express request?
Two options:
Create your own mock object:
describe('Utils', () => {
/**
* Mocked Express Request object
*/
let mockedReq;
beforeEach(() => {
mockedReq = {
query: {}
};
})
it('checkMandatoryQueryParams', () => {
const req = mockedReq;
req.query = "?foo=test&bar=test"; // pseudo-code
expect(checkMandatoryQueryParams(['foo', 'bar'], req) ).toEqual(true);
});
});
Use manual mocks, similar to above:
describe('Utils', () => {
/**
* Mocked Express Request object
*/
let mockedReq;
beforeAll(() => {
mockedReq = jest.fn().mockImplementation(() => {
const req = {
// Implementation
};
return req;
});
});
beforeEach(() => mockedReq.mockReset())
it('checkMandatoryQueryParams', () => {
const req = mockedReq;
req.query = "?foo=test&bar=test"; // pseudo-code
expect(checkMandatoryQueryParams(['foo', 'bar'], req) ).toEqual(true);
});
});

How to mock pg-promise library with jest

I am trying to mock the pg promise library. I want to be able mock return whether the promise rejects or resolves. Here is an example function and test:
const pgp = require('pg-promise')({});
const someFunc = callback => {
const db = pgp('connectionString');
db
.none('create database test;')
.then(() => {
callback(null, 'success');
})
.catch(err => {
callback(err);
});
};
module.exports = {
someFunc
};
And i wanna test it like so:
const { someFunc } = require('./temp');
let pgp = require('pg-promise')({
noLocking: true
});
// HOW TO MOCK?
describe('test', () => {
beforeEach(() => {
jest.resetModules();
jest.resetAllMocks();
});
it('should test', () => {
let db = pgp('connectionString');
// how to mock this?
db.none = jest.fn();
db.none.mockReturnValue(Promise.reject('mock'));
const callback = jest.fn();
someFunc(callback);
return new Promise(resolve => setImmediate(resolve)).then(() => {
expect(callback.mock.calls.length).toEqual(1);
});
});
});
You can mock the pgp object with a dumb mock like so:
const { someFunc } = require('./temp');
let pgp = jest.fn(() => ({
none: jest.fn(),
})
jest.mock('pg-promise') // Jest will hoist this line to the top of the file
// and prevent you from accidentially calling the
// real package.
describe('test', () => {
beforeEach(() => {
jest.resetModules();
jest.resetAllMocks();
});
it('should test', () => {
let db = pgp('connectionString');
db.none.mockRejectedValue('mock'); // This is the mock
const callback = jest.fn();
someFunc(callback);
return new Promise(resolve => setImmediate(resolve)).then(() => {
expect(callback.mock.calls.length).toEqual(1);
});
});
});
Its an old question, but here is a new answer:
You can have a look at pg-mem, a library I released recently which emulates an in-memory postgres instance.
It supports most of the usual SQL queries (but will fail on less frequent syntaxes - file an issue if you encounter such a situation).
I wrote an article about it here
For your use case, see the this section