Sinon not mocking method - node.js

I want inject into constructor database client, but when I run tests, mocha throw exception, that method whitch is called is not a function.
export class CustomService {
constructor(database: any) {
database.init().then((res)=>{}));
}
}
describe('CRUD service', ()=>{
it('when i decide save item', ()=>{
let db = sinon.mock(new DatabaseService);
let instance = new CustomService(db);
db.expects('init').once();
db.verify();
});
});
In console:
TypeError: database.init is not a function
What is wrong?

Don't pass the return value of sinon.mock to the code you are testing but instead pass the original object you passed to sinon.mock. The return value of sinon.mock is only for setting assertions and checking them. You also need to set the order of the statements in your tests so that the expectations are set before the code that must satisfy them is run. Something like this:
describe('CRUD service', ()=>{
it('when i decide save item', ()=>{
const db = new DatabaseService();
let mock = sinon.mock(db);
mock.expects('init').once();
let instance = new CustomService(db);
mock.verify();
});
});

Related

NodeJS Unit test how to spy/stub

I am stuck on this for few days now.
while testing my handler function I would like to "fake" the call to rotateApiKeys fonction I was thinking to use stubs to achieve that.
But first I would like to see if at least I could spy on rotateApiKeys while calling the handler, so far I am getting:
AssertError: expected rotateApiKeys to be called once but was called 0 times and I can see that function actually been called.
Questions:
What would you recommend me to use? Mock/Stub/Spy
If Spy should work, why I am getting that assertError?
Handler:
async function handler(event) {
// declare a new JSON object
let handlerObject = {
"event": event,
"isValidEvent": rotateFunctions.validateEvent(event),
"actionCountObject": {}
};
if (handlerObject.isValidEvent) {
// continue here
handlerObject.actionCountObject = await rotateApiKeys(event);
}
// console log JSON handlerObject
console.log("handlerObject: " + JSON.stringify(handlerObject));
// return the object
return handlerObject;
}
unit test code:
it("Should call rotate", async function() {
var rotate = sinon.spy(rotateApiKeys, 'rotateApiKeys');
const result = await rotateApiKeys.handler(event);
rotate.restore();
sinon.assert.calledOnce(rotate);
});

How to do callback in our component using react jest test cases

How can we do callback on success and failue cases for below lines of code for test coverage using jest
const handleService = () => {
window.domain.service("1321",'',onSuccess, onFailure)
}
const onSuccess = () => {
....update state values
}
const onFailure = () => {
....update state values
}
Something like this:
Spy on window.domain.service to gain access to the calls it receives. This will allow you to access the parameters of those calls which will be "1321",'',onSuccess, onFailure
Assign the function you wish to test to a variable
Invoke the function to execute the code in it (this will get you the coverage)
(Optional) assert that the callback functions behave correctly
Here is a snippet to help demonstrate
it('should run', () => {
// Some setup to create the function on the window, may not be needed if done elsewhere.
// Could be good to do this in a beforeEach and clean up in afterEach to avoid contaminating the window object
window.domain = {
service: () => {},
}
// Spy on the window.domain.service method.
// Provide a mock implementation if you don't want the real one to be called
const serviceSpy = jest.spyOn(window.domain, 'service');
executeYourCode();
// capture the arguments to the call
const [_arg1, _arg2, onSuccess, onFailure] = serviceSpy.mock.calls[0];
// execute the callbacks
onSuccess();
onFailure();
});

sinon stub namespaced function

I'm having some issues using sinon stubs and it may stem from how I'm implementing namespacing on the module that I'm looking to stub. Methods directly defined on the prototype are stubbed as I would expect.
...my module.js
const Constructor = require('./constructor') //...just exports a singleton
/* Need to namespace some of my functions and retain the `this` context */
Object.defineProperty(Constructor.prototype, 'es', {
get: function() {
return {
method: require('./implementations/doesSomething.js').bind(this)
}
}
});
module.exports = Constructor;
/* ...testFile.js */
const Constructor = require('./constructor');
const instance = new Constructor();
const sinon = require('sinon');
sinon.stub(instance.es, 'method', function() {
return 'hijacked original method'
});
As mentioned on the Sinon issue tracker, the problem here is that using a plain Object.defineProperty(obj, 'prop') call does something else than plainly creating it using assignment (obj['prop'] = ...).
Generally, if you try defining your property without Object.defineProperty it will be stubbable, but using defineProperty (without creating a special configuration) will make it impossible to stub the property. The reason is simply that the default values for writeable and configurable are false! You cannot delete them or change them. And if you can't do that, then Sinon won't help you. So, generally, you need to add writeable: true, configurable: true in your property definition.
Now there was one more thing I forgot to answer originally:
You are not trying to wrap a function on Constructor.prototype.es.method - what you are trying to wrap is the function on the object returned by the getter on the property for es. That will never work. Why? Simply because the returned object is never the same. You are creating a new object around method each time. If you really need to replace/stub the method property, you actually need to replace the entire Constructor.prototype.es property instead. If you need this namespacing, you can vastly simplify this, and also enable stubbing, like this:
Constructor.prototype.es = {};
Object.defineProperty(Constructor.prototype.es, 'method', {
get: function() {
return someFunction.bind(this);
},
writeable: true,
configurable:true
}
An expanded, fully working example (Gist for download):
// constructor.js
const someFunction = function(){
return this.value;
}
function Constructor(){ };
Constructor.prototype.es = { value : 100 };
Object.defineProperty(Constructor.prototype.es, 'method', {
get: function() {
return someFunction.bind(this);
},
writeable: true,
configurable:true
});
// test.js
const instance = new Constructor();
console.log(instance.es.method()) // => 100
// using this won't work:
// sinon.stub(instance.__proto__.es, 'method').returns(42);
// because the getter is returning a _new_ function each time
// therefore you need to attack the actual getter function:
const stub = sinon.stub(instance.__proto__.es, 'method').value(()=>42);
console.log(instance.es.method()) // => 42
stub.get(()=>()=>84);
console.log(instance.es.method()) // => 84
stub.restore();
console.log(instance.es.method()) // => 100
// the above is working on the prototype, can't we do this on the instance?
// yes, we can, but remember that the `es` object is shared, so we
// can avoid modifying it by shadowing it further down the prototype
instance.es = { method: sinon.stub().returns(256) };
console.log(instance.es.method()) // => 256
delete instance.es
console.log(instance.es.method()) // => 100
<script src="https://unpkg.com/sinon#2.3.5/pkg/sinon.js"></script>

Testing Promises with multiple thens using testdoublejs

I am using testdouble for stubbing calls within my node.js project. This particular function is wrapping a promise and has multiple then calls within the function itself.
function getUser (rethink, username) {
return new Promise((resolve, reject) => {
let r = database.connect();
r.then(conn => database.table(tablename).filter({username}))
.then(data => resolve(data))
.error(err => reject(err));
});
}
So I am wanting to determine if the resolve and reject are handled correctly based on error conditions. Assume there is some custom logic in there that I need to validate.
For my test
import getUser from './user';
import td from 'testdouble';
test(t => {
const db = td.object();
const connect = td.function();
td.when(connect('options')).thenResolve();
const result = getUser(db, 'testuser');
t.verify(result);
}
The issue is that the result of connect needs to be a promise, so I use then resolve with a value which needs to be another promise that resolves or rejects.
The line it is relating to is the result of database.connect() is not a promise.
TypeError: Cannot read property 'then' of undefined
Anyone have success with stubbing this type of call with Test Double?
So figured out the resolution. There are a few things to note in the solution and that we encountered. In short the resolution ended up being this...
td.when(database.connect()).thenResolve({then: (resolve) => resolve('ok')});
This resolves a thenable that is returned when test double sees database connect. Then subsequent calls can also be added.
There is also a part to note if you send in an object to database.connect() you have to be aware that it is doing === equality checking and you will need to have a reference to that object for it to correctly use td.when.
Test double provides stubs for unit testing. And in your case 'db' is the object we need to mock. Creating the mocking db through
td.object(Database) // Database is the class or constructor of your db
will be the right choice, but to simply mock those methods you need in this case, I wouldn't pick that way.
Here's the tested module, 'some.js':
function getUser (database, username) {
return new Promise((resolve, reject) => {
let r = database.connect();
r.then(conn => database.table('table').filter({username:username}))
.then(data => resolve(data))
.catch(err => reject(err));
});
}
module.exports = getUser;
And the test file, using mocha and chai.expect, which is could also be any other unit test module here:
let td = require('testdouble');
let expect = require('chai').expect;
const getUser = require('./some');
describe('some.js',()=>{
it('getUser',()=>{
const db = {};
const name = 'name';
db.connect = td.function();
db.table = td.function('table');
db.filter = td.function('filter');
td.when(db.connect()).thenResolve(db);
td.when(db.table('table')).thenReturn(db);
td.when(db.filter({username: name})).thenResolve('some user data');
return getUser(db, name)
.then(user=>{
expect(user).to.equal('some user data')
})
.catch(e=>assert(e))
})
})
So please let me know if any of these confuse you.

Jasmine spyOn function argument object, as Variables are not defined

I am wiring jasmine test cases for one of the application. I have just started learning jasmine.
Below is my script code
var aclChecker = function(app,config) {
validateResourceAccess = function (req, res, next) {
req.callanotherMethod();
res.send(401,'this is aerror message');
}
}
Now i want to spyOn res and req object to know if send method has been called.
As req and res are not global variables i am having this doubt on how to create a spy on in junit spec
Please help!!!!!!!!
You can simply mock req and res like this.
describe("acl checker", function() {
it("should validate resource access", function() {
var mockReq = {
callAnotherMethod: function() {}
};
var mockRes = {
send: function() {}
};
var mockNext = {};
spyOn(mockReq, "callAnotherMethod");
spyOn(mockRes, "send");
aclChecker.validateResourceAccess(mockReq, mockRes, mockNext);
expect(req.callAnotherMethod).toHaveBeenCalled();
expect(res.send).toHaveBeenCalledWith(401, 'this is aerror message');
});
});
Typically, in a unit test you would mock any resource requests and only validate that the request is proper. So you would instead call a mock request library, and validate that the url and headers are correct.
However, if you really want to test the actual access to the resource, you will need to build your request object first, and give yourself access to it afterwards.
If you want to learn about request mocking, check out jasmine-ajax:
https://github.com/pivotal/jasmine-ajax
If you still want to do this, you should use a beforeEach function in the test file to create the dependencies you need for your tests.
Take a look at this for more help with beforeEach:
https://github.com/pivotal/jasmine/wiki/Before-and-After

Resources