Jasmine junit testing of delegate callback of function args - javascript

I have recently started using jasmine to write junit testcase for one of our application.
I am stuck at this point on how to call the callBack function of the spied function.
setProfile :function(userProfile,callback){
var user;
var subjectInfo;
iService.searchForAccess(subjectInfo , queryCalback);
function queryCalback(err, userProfile) {
if(err){
callback(true,errorMessage)
}else{
callback(false,null)
}
}
}
Now in my spec i want to mock the call to iService.searchForAccess real world implementation and want to call nocallThrough for searchForAccess . but my queryCalback function has to be called for complete use case coverage.
In my spec i have tried to call queryCalback function explicitly by
spyOn(iService,'searchForAccess');
iService.searchForAccess.mostRecentCall.args[1](error, userProfile);
but iService.searchForAccess.mostRecentCall returns {}, empty object.
kindly help!!!!!!!!!!
Regards
Punith

I have used sinonjs as solution to above problem statement. Below is the syntax of how its done.
var sinon = require('../node_modules/sinon/lib/sinon.js');
sinon.stub(iService, 'searchForAccess').callsArgWith(1, mockSubjectInfo, session.userProfile);
Hope it will be helpfull to others.
Regards
Punith

Related

sinon spy not detecting a function call

I'm trying to use sinonJS framework for nodeJS unit tests. The problem is, I cannot get the sinon spies working at all. This is my code:
const callback = sinon.spy(someModule.callback)
mainModule.doSomethingFunction() //someModule.callback function is called inside this function
assert(callback.calledOnce, 'callback should be called once')
It just fails with:
AssertionError: callback should be called once
But I'm logging inside the function that should be called, and it clearly shows it is being called, the sinon spies just doesn't detect it. I wonder what is wrong?
To wrap an object method in a spy, you can use sinon like this:
const callback = sinon.spy(someModule, 'callback');
mainModule.doSomethingFunction();
assert(callback.calledOnce, 'callback should be called once');
callback.restore();
Note that you should call restore when you are done to unwrap the spy.
The statement const callback = sinon.spy(someModule.callback) creates a spy that will call the someModule.callback once it is called (BTW it is not a constant) but it doesn't replace the someModule.callback function. To replace the function use someModule.callback = sinon.spy(someModule.callback)

How to mock or callFake a basic javascript function?

I've two functions funcA() and funcB(), I'm writing unit test cases for $scope.funcA().
Below is the the definition:
function funcB(){
//statements
console.log("At function B");
};
$scope.funcA() = function(){
funcB();
console.log("At function A");
};
Right now while I'm testing my $scope.funcA() is actually calling my funcB(). How to stop this and make a fake call or mock to funcB(); in Jasmine.
you can use spyOn() and andCallFake() to achieve it.
see one of my earlier answer here .
Does Jasmine's spyOn() allow the spied on function to be executed?
hope this helps.
EDIT
for newer versions of jasmine, the snytax would be
spyOn($scope, 'funcB').and.callFake(function() {
return 'something';
});
for a complete list, see - http://jasmine.github.io/2.0/introduction.html

Javascript Unit testing and refactoring (using Angular js framework)

I (as a js/ng newbie) wanna know how do I start on my unit-test journey for the following angular code (Controller with some functions) and mocking necessary? Basically, I want to test extracted() function. Would appreciate beautiful suggestions. Thanks
angular.module('HelloWorld')
.controller('myCtrl', function ($scope, firstService, secondService, messageService) {
'use strict';
function goWhereTheWindBlows() { // some implementation }
$scope.mainFun = function(var1) {
firstService.showSomething(var1, function() {
var result = secondService.read(var1);
// result is the result of http get (200 or 400)
extracted(result);
}, goWhereTheWindBlows);
function extracted(result) {
result.then(function () {
messageService.addMessage({ message: 'Success', type: 'standard' });
}, function () {
messageService.addMessage({ message: 'Failure', type: 'error' });
});
}
};
});
Use grunt-karma to perform unit tests.
You should have tests folder in your structure.
Write unit test for this code in jasmine syntax.
use beforeEach to use module in which your controller is.
create variable and assign controller to it using $controller function.
Take variable with controller and run expect on your method in it function.
Thats it, run grunt test and see the results.
Some explantation about writing in jasmine syntax.
For mocking http data - that one used with $http service, use $httpBackend service in angular-mocks.js.
This is fake backend in which you write for example get requests, and specify answers from this using whenGET() and expect. There are also other requests like POST, PUT. Basically after defining result expectation you use $httpBackend.flush() method to flush changes, so your would retrieve data.
There are also end to end tests, which you can perform with protractor using selenium webdriver, but these are hard to integrate with grunt test, so you may run all tests as two commands.
Note that end to end tests are not in jasmine syntax, so you write them different.

How to create test doubles with Sinon that prevents execution of the actual function

I am doing javascript unit testing with Mocha and Sinon. I want to test whether under certain circumstances, a certain method is called.
However, so far I couldn't manage only to test if the method was called. To make it clearer, I want a fake method to replace the actual method, because I don't want to simulate my whole application state to make this simple test pass.
This is my actual test code:
it('calls the handleResults method when its model syncs', function () {
var spy = sinon.stub( this.appview, 'handleResults' );
this.appview.model.fetch();
server.requests[0].respond( 200,
{ "Content-Type": "application/json" },
JSON.stringify( [ { id: "casa", text: "Something" } ] )
);
spy.should.have.been.called;
});
The real this.appview.handleResults method is being called, while I would want to call a fake version which does nothing else than checking whether it was called or not.
What am I doing wrong?
The docs are very clear that by using stub, the original function will be replaced by mock and will not be called:
As spies, stubs can be either anonymous, or wrap existing functions.
When wrapping an existing function with a stub, the original function
is not called.
and
var stub = sinon.stub(object, "method");
Replaces object.method with a
stub function. The original function can be restored by calling
object.method.restore(); (or stub.restore();). An exception is thrown
if the property is not already a function, to help avoid typos when
stubbing methods.

Unit testing with Jasmine: code in beforeEach() not seen by test's spyOn()

New to unit testing in general and Jasmine in particular.
I've set a variable in a beforeEach() callback, but it doesn't seem to work on the second test. It's supposed to fire initialization stuff in advance of every test within its context, right? I'm sure my spyOn() call is to blame, but I don't know how to fix it.
Comments explain the passes and fails:
describe("Test suite for my library", function () {
var html,
body,
play,
...
// custom matcher...
beforeEach(function () {
this.addMatchers({
toBeInstanceOf : function (constructr) {
return this.actual instanceof constructr;
});
});
});
describe("Within the Button object", function () {
beforeEach(function () {
play = new Button("play", false);
});
describe("play", function () {
// This test passes, as expected...
it("should be an instance of the Button object", function () {
expect(play).toBeInstanceOf(Button);
});
});
describe("play.name", function () {
// This test failed with the message
// "Expected spy Button to have been called
// with [ 'play', false ] but it was never called."
it("should be the first argument passed to the Button constructor", function () {
spyOn(window, "Button");
play = new Button("play", false); // ...until I added this line. Now it passes.
expect(window.Button).toHaveBeenCalledWith("play", false);
});
// This test passes, even if the one above fails.
it("should be 'play'", function () {
expect(play.name).toBe("play");
});
});
});
});
The documentation explains the usage, but not the context, of spyOn(), so I can't tell if I've created a bug or if I'm unknowingly taking advantage of a feature.
I can post the constructor if anyone thinks it makes any difference in the diagnosis, but I can assure you it's dead simple.
I'm sure it's a straightforward fix using some basic unit testing concept I'm having to learn the hard way. Thanks in advance.
P.S. I realize what I'm testing for in that failing spec isn't what I've described. I'm working my way through the API guide, looking for a way to get to the arguments array within a function call, so I can do a specific test on arguments[0]. Hints are appreciated, but not necessary. I'll figure it out.
Short answer: No, Before each and spies are not incompatible
You must Spy before you call if you want the spy to know about the call. You can use spyOn(object, 'function').andCallThrough() if you do not wish to interfere with its default behavior.
Long answer: The way faking/mocking/stubbing/spying frameworks often work is by replacing the method you are calling with a method that the mocking framework can control. Any calls to that function before it is replaced with the spy cannot be observed. This is a good thing, though mildly inconvenient,
Its cause you spy on window.Button after you have called. Im not totally sure what spy does, but after all it displaced the function you spy on with another function where it can check the function was called and whats arguments was passed. When you create your Button before your start your test, the original window.button function called. Then you replaces the function with the spy and test that the spy was called, so your test must fail.
Seems either create your Button in the test itself or create your spy before you call new Button in your beforeEach function.

Categories