How to cover arrow functions in unit testing in angular? - node.js

this.service = () => { -- statements -- }
The above statement is to be tested using jasmine unit testing in angular.
Can i get some suggestions for that ?
it("should service call",()=>{ // i want to call the arrow function here like component.service.? what to use in place of '?'. })

It is a function so you call it immediately:
example:
interface Service {
fun: () => string;
}
class Component {
constructor() {
this.service = () => {
return {
fun: () => 'hello'
};
};
}
service: () => Service;
}
Calling it:
const component = new Component();
const service = component.service();
const message = service.fun();
// or in one line:
const message = new Component().service().fun();
Typescript playground example

Related

Jest SpyOn __mocks__ module

We mock our modules using __mocks__. I'd like to spyOn a module function in my test but it doesn't seem to be working. Related question, I'd also like to override a mocked module function for a test (ie throw an exception). How can I do this?
├──__mocks__
| └──DB-Utils.js
| └──controllers
| └──myController.js
├──node_modules
__mocks__/DB-Utils.js:
const { MyController } = require('./controllers/myController');
module.exports = {
MyController,
};
__mocks__/controllers/myController.js:
class MyController {
async setAvailability(id, availability) {
return true;
}
}
module.exports = {
MyController,
};
test.spec.js:
const { MyController } = require('DB-Utils');
const myController = new MyController();
describe('Register Tests', () => {
fit('myController setAvailability', async () => {
---code that calls a class that ends up calling myController.setAvailability---
expect(myController.setAvailability).toHaveBeenCalledWith('foo', 'bar');
});
});
My tests pass in that the mock myController is called, however it fails the toHaveBeenCalledWith with an error of Number of calls: 0
How can I spy setAvailability?
For the related question I'd also like to be able to do something like the following:
describe('Register Tests', () => {
fit('myController setAvailability throws', async () => {
jest.spyOn(myController, 'setAvailability').mockImplementation(() => {
throw new Error()
});
expect(---code that calls a class that ends up calling myController.setAvailability---).toThrow();
});
});

can't get the Jest provided ESM example to run

I'm just trying to get the ES6 Class Mocks example provided by Jest to run green.
here's my code repo
it's taken me way to long to even get to this point, but the tests still fail with
TypeError: SoundPlayer.mockClear is not a function
system under test
import SoundPlayer from './sound-player';
export default class SoundPlayerConsumer {
constructor() {
this.soundPlayer = new SoundPlayer();
}
playSomethingCool() {
const coolSoundFileName = 'song.mp3';
this.soundPlayer.playSoundFile(coolSoundFileName);
}
}
the test
import {jest} from '#jest/globals';
import SoundPlayer from './sound-player';
import SoundPlayerConsumer from './sound-player-consumer';
const mockPlaySoundFile = jest.fn();
jest.mock('./sound-player', () => {
return jest.fn().mockImplementation(() => {
return {playSoundFile: mockPlaySoundFile};
});
});
beforeEach(() => {
SoundPlayer.mockClear();
mockPlaySoundFile.mockClear();
});
it('The consumer should be able to call new() on SoundPlayer', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
// Ensure constructor created the object:
expect(soundPlayerConsumer).toBeTruthy();
});
it('We can check if the consumer called the class constructor', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
expect(SoundPlayer).toHaveBeenCalledTimes(1);
});
it('We can check if the consumer called a method on the class instance', () => {
const soundPlayerConsumer = new SoundPlayerConsumer();
const coolSoundFileName = 'song.mp3';
soundPlayerConsumer.playSomethingCool();
expect(mockPlaySoundFile.mock.calls[0][0]).toEqual(coolSoundFileName);
});
system under test dependency
export default class SoundPlayer {
constructor() {
this.foo = 'bar';
}
playSoundFile(fileName) {
console.log('Playing sound file ' + fileName);
}
}

Sinon Stub depedent class in node.js module

I have one class as below
nx-user.js
class NXUser {
constructor() {}
view(guid, data) {
//do something
}
}
Then I have user controller module as below which has dependency of NxUser class
userController.js
const userDb = new NXUser();
import NXUser from "../../../persistence/nx-user";
const allUsers = () => {
return userDb.view()
}
export {allUsers }
I have below code written for stubbing view function of NxUser class for controller unit tests. But its not working. It always calling actual one instated of stubbed one
userController-test.js
let userdb=NXUser();
describe("user controller", function () {
let stubValue = [{
"name": "Urvashi Parmar",
"email": "urvashi.parmar#nationalexpress.com"]}
it("Should create user", () => {
sinon.stub(userdb, 'create').resolves(stubValue);
userController.allUsers ().then((body) => {
expect(body[0].name).to.equal(stubValue .name);
done();
});
})
}
Because I can not comment yet, so I need to give full answer.
Confusion: at your userController-test.js, you are trying to test NXUser.create, while at file nx-user.js has no definition of create.
Assume: you are trying to test NXUser.view.
This example is created based on your code, and is working fine. Console log "Called" will not get called.
Highlight:
Stub NXUser view directly, not userdb.create;
I use async-await inside test.
const sinon = require('sinon');
const { expect } = require('chai');
class NXUser {
constructor() {}
view(guid, data) {
console.log('Called');
return new Promise((resolve) => resolve([]));
}
// Add this only for dummy.
create() {
return new Promise((resolve) => resolve([]));
}
}
const userController = {
allUsers() {
const userDb = new NXUser();
return userDb.view();
}
}
describe('user controller', function () {
// Suppose you test view user.
it('should view user', async function () {
const stubValue = [{
name: 'Urvashi Parmar',
email: 'urvashi.parmar#nationalexpress.com'
}];
// Suppose you stub method view and not create.
const stubUserDBView = sinon.stub(NXUser.prototype, 'view');
stubUserDBView.resolves(stubValue);
const body = await userController.allUsers();
expect(body).to.be.an('array').that.have.lengthOf(1);
expect(body[0]).to.have.property('name', stubValue[0].name);
// Restore stub.
stubUserDBView.restore();
});
});
$ npx mocha stackoverflow.js
user controller
✓ should view user
1 passing (11ms)
$
Hope this helps.

Make partial mock of class with Jest in NodeJS

I'm new to NodeJS and came from PHP, where creating partial mock was easy. But I'm not able to accomplish the same with Jest in NodeJS.
I have a function extractPayloadDates which accept an instance of dialogflow Agent and taking and parsing data from it. I want to mock only single method getParameter of Agent, because no more methods are used in the tested function. I found this code online but it doesn't work
import { Agent } from '../../src/dialogflow/Agent';
import { extractPayloadDates } from '../../src/intents/extractPayloadDates';
describe('extractPayloadDates', () => {
it('tests extracting string', () => {
const AgentMock = jest.fn<Agent, []>(() => ({
getParameter: () => {
return 'some date';
}
}));
const agent = new AgentMock();
expect(extractPayloadDates(agent)).toEqual('some date');
});
});
This code produce following error:
Type '{ getParameter: () => string; }' is missing the following properties from type 'Agent': payload, webhookClient, chatter, getOriginalRequest, and 13 more.ts(2740)
index.d.ts(124, 53): The expected type comes from the return type of this signature.
I also tried to use jest.spyOn, but the problem is, that I cannot create Agent instance as it needs many other objects.
Edit 3.9.2019 with more code
Agent.ts
export class Agent {
private payload: DialogFlowPayload[] = [];
constructor(readonly webhookClient: WebhookClient, private readonly chatter: Chatter) {}
...
}
WebhookClient and Chatter have more dependencies in their constructor as well...
extractPayloads.spec.ts
import { Agent } from '../../src/dialogflow/Agent';
import { extractPayloadDates } from '../../src/intents/extractPayloadDates';
describe('extractPayloadDates', () => {
it('tests extracting string', () => {
const webhookMock = jest.fn();
const chatter = jest.fn();
const agent = new Agent(webhookMock, chatter);
expect(extractPayloadDates(agent)).toEqual('some date');
});
});
This produce another error:
Argument of type 'Mock' is not assignable to parameter of type 'Chatter'.
Property 'getMessage' is missing in type 'Mock' but required in type 'Chatter'
Do I really have to create also WebhookClient and all its dependencies and do the same with Chatter? If I do, I have to create instances of multiple classes just to mock 1 method in Agent, which then will not use any of dependency.
From the docs of jest
If you want to overwrite the original function, you can use jest.spyOn(object, methodName).mockImplementation(() => customImplementation) or object[methodName] = jest.fn(() => customImplementation);
jest.spyOn call jest.fn internally. So you can only mock getParameter method of agent like this:
extractPayloadDates.ts:
function extractPayloadDates(agent) {
return agent.getParameter();
}
export { extractPayloadDates };
Agent.ts:
interface DialogFlowPayload {}
interface WebhookClient {}
interface Chatter {
getMessage(): any;
}
class Agent {
private payload: DialogFlowPayload[] = [];
constructor(readonly webhookClient: WebhookClient, private readonly chatter: Chatter) {}
public getParameter() {
return 'real data';
}
public otherMethod() {
return 'other real data';
}
}
export { Agent, Chatter };
Unit test, only mock getParameter method of agent, keep the original implementation of otherMethod
import { extractPayloadDates } from './extractPayloadDates';
import { Agent, Chatter } from './Agent';
const webhookMock = jest.fn();
const chatter: jest.Mocked<Chatter> = {
getMessage: jest.fn()
};
const agent = new Agent(webhookMock, chatter);
describe('extractPayloadDates', () => {
it('should only mock getParameter method of agent', () => {
agent.getParameter = jest.fn().mockReturnValueOnce('mocked data');
const actualValue = extractPayloadDates(agent);
expect(actualValue).toEqual('mocked data');
expect(agent.otherMethod()).toBe('other real data');
});
});
PASS src/stackoverflow/57428542/extractPayloadDates.spec.ts
extractPayloadDates
✓ should only mock getParameter method of agent (7ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.484s, estimated 3s

testing an actual returning value on javascript using jest

I have the following js function:
const modelUtils = {
modelingObj(obj, stringVal = ‘RE’) {
let newObj;
//my logic for setting value of newObj
return newObj;
};
export default modelUtils;
I want to test and see that based on a specific params I get a particular result, the issue is I’m always returning back an empty object.
Test.js
import modelUtils from '../modelUtils';
jest.unmock('../modelUtils');
describe(' testing modelUtils', () => {
let test;
const mockData = {
myProperty: [],
};
describe('testing modelingObj function', () => {
it('For my first test’, () => {
test = modelUtils.mockData, ‘TR’);
expect(test).toEqual({ myProperty: [] });
});
});
});

Resources