I would like to mock value ENV_JWT_ENABLED peer test. I would like to use new value A in first test and new value B in second test. But I am getting still foo from global mock.
My current solution not working.
import { JwtAuthGuard } from './jwt-auth.guard';
jest.mock('const/env', () => ({
ENV_JWT_ENABLED: 'foo'
}));
describe('test', () => {
it('A', () => {
jest.mock('const/env', () => ({
ENV_JWT_ENABLED: 'new value A'
}));
const instance = new JwtAuthGuard(); // will print foo inside
});
it('B', () => {
jest.mock('const/env', () => ({
ENV_JWT_ENABLED: 'new value B'
}));
const instance = new JwtAuthGuard(); // will print foo inside
});
});
jest always prefered global vs within block, better using mockImplementationOnce with
mockImplementation provide you to mock value based on its call.
you can refer https://jestjs.io/docs/en/mock-function-api#mockfnmockimplementationoncefn chaining of mock for fn.
import { JwtAuthGuard } from './jwt-auth.guard';
jest.mock('const/env', () => {
return {
ENV_JWT_ENABLED: jest
.fn()
.mockImplementation()
.mockImplementationOnce(() => {
return 'new value A';
})
.mockImplementationOnce(() => {
return 'new value B';
})
};
});
describe('test', () => {
it('A', () => {
const instance = new JwtAuthGuard(); // will print new value A inside
});
it('B', () => {
const instance = new JwtAuthGuard(); // will print new value B inside
});
});
jest.mock at test level cannot affect top-level imports. jest.isolateModules or jest.resetModules can be used in conjunction with require or dynamic import to provide test-specific module mocks:
it('A', () => {
jest.isolateModules(() => {
jest.mock('const/env', () => ({
ENV_JWT_ENABLED: 'new value A'
}));
const { JwtAuthGuard } = require('./jwt-auth.guard');
const instance = new JwtAuthGuard();
});
});
Related
I am using firebase admin and I am trying to write some unit tests for my code.
Since admin is injected in my function I figured I could mock a very simple object like this:
admin = {
get auth () {
return {
updateUser: () => {
return true;
},
createUser: () => {
return true;
},
getUser: () => {
throw Error('no user');
}
};
}
};
Then in a particular test I can stub the functions. Here is what I have done so far:
// stubbed functions
sinon.stub(admin, 'auth').get(() => () => ({
updateUser: () => ({ called: true }),
getUser: () => (userRecord),
createUser: () => ({ called: false })
}));
and those are working fine (I can see with my logs).
However in my test I would also want to check if createUser has been called at all.
I thought I could set up a spy on the createUser function, but so far I can't really get it to work.
Here is what I have been trying (with a bunch of variation always failing):
it.only('should update a user', async () => {
const userRecord = mockData
sinon.stub(admin, 'auth').get(() => () => ({
updateUser: () => ({ called: true }),
getUser: () => (userRecord),
createUser: () => ({ called: false })
}));
const spy = sinon.spy(admin, 'auth', ['get']); // this is not working
const user = await upsertUser(data, firestore, admin);
expect(user).toEqual(data.userDataForAuth); // this one is ok
sinon.assert.calledOnce(spy.get); // this throws an error
});
the bit of code I am trying to test (which is the upsert function is this:
// in my test exisiting user is not null (the stub `getUser` is returning a object
if (existingUser != null) {
try {
await admin.auth().updateUser(uid, userDataForAuth);
return userDataForAuth;
} catch (error) {
console.log('error', error);
throw Error('error updating user');
}
}
I am not even sure this is the best approach, happy to change it if there is a better one!
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
I have to make a test for a vue instance using jest and the test includes a confirm pop up, question is how to simulate click on "Yes" in the pop up. I was trying to use:
window.confirm = jest.fn(() => true);
and:
window.confirm = () => true;
and inventing something like that:
wrapper.confirm = () => true;
But no luck, maybe someone had similar problem?
Since we're running the tests in Nodejs we can reference confirm as global.confirm and If we want to test the function add if it adds 2 whenever confirm returns true we can do this:
const add = require('./add');
describe('add', () => {
describe('confirm returning true', () => {
let result;
beforeAll(() => {
// we define confirm to be a function that returns true
global.confirm = jest.fn(() => true);
result = add(1);
});
it('should call confirm with a string', () => {
expect(global.confirm).toHaveBeenCalledWith(
expect.any(String),
);
});
it('should add two', () => {
expect(result).toBe(3);
});
});
describe('confirm returning false', () => {
let result;
beforeAll(() => {
// we define confirm to be a function that returns false
global.confirm = jest.fn(() => false);
result = add(1);
});
it('should call confirm with a string', () => {
expect(global.confirm).toHaveBeenCalledWith(
expect.any(String),
);
});
it('should NOT add two', () => {
expect(result).toBe(1);
});
});
});
online working example
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
I am testing a angular component and the code is
ngOnInit(): void {
this.getNar();
}
getNar(): void {
let self = this;
this.dashboardService.getNar().subscribe(
res => self.narIds = res.narIds,
error => self.error = error,
function () {
self.narIds.forEach(element => {
// Some Code
});
}
);
}
The Service provider for this i.e Dashboard Service is
getNar(): Observable<any> {
return this.http.get(Config.Api.GetNar + '1/nar').map((res: Response) => res.json());
}
And my Test cases are:
let res = '"narIds":[{"id":1,"narId":"104034-1","narName":"SDLC Platform"},{"id":2,"narId":"64829-1","narName":"EMS-EMS"}]';
describe('Application Health Component', () => {
beforeEach( async(() => {
TestBed.configureTestingModule({
providers: [MockBackend, DashboardService],
imports: [ChartsModule, SlimScrollModule, HttpModule],
declarations: [CompletedFilterPipe, ApplicationHealthComponent]
})
.compileComponents()
.then(createComponent);
}));
it('should call the getNar when ngOnInit is called', async(() => {
spyOn(dashboardService, 'getNar').and.returnValue(Observable.of(res));
comp.ngOnInit();
expect(dashboardService.getNar).toHaveBeenCalled();
}));
});
function createComponent() {
fixture = TestBed.createComponent(ApplicationHealthComponent);
comp = fixture.componentInstance;
dashboardService = fixture.debugElement.injector.get(DashboardService);
};
The problem I am getting is the test case gives an error that forEach is undefined.
The error message is not that forEach function is not defined, it's that your object "self.narIds" is undefined. Fairly sure this is due to the way you declared your onComplete function in Observable.subscribe
related to this Rx Subscribe OnComplete fires but cannot use the data
change your
function () {
self.narIds.forEach(element => {
// Some Code
});
code to
() => {
self.narIds.forEach(element => {
// Some Code
});