How to mock or callFake a basic javascript function? - javascript

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

Related

Testing Javascript function using Jasmine

I have a problem when I'm trying to test some javascript, I'm not sure that the code is actually testable, but then I would be pleased to know how to make it testable.
$("#Button").on('touchstart', () => testFunc());
function testFunc() {
button(true, userInfo, gameCode);
}
I want to test when the button is touched that the testFunc is called. I'm using Jasmine as my test framework.
But for whatever reason when I try to call the testFunc from Jasmine just to test that something is working I get the error
"ReferenceError: Can't find variable: testClass in file:///E:/Dokumenter/SemesterProjekt%20fun%20stuff/PRJ4Web/TankWebApplication/TankWebApplication/Test/Test.js (line 8)s"
I have made the reference to the file. So I'm not sure what is going on.
The test code that gives me the error
describe("Joystick test for functionallity",
function() {
beforeEach(function() {
});
it("All default values",
function() {
testFunc();
});
});
How do I test this code? Is it possible to do?
Your goal is to see if the function will be called upon button click, therefore, you must check the actual function call with
toHaveBeenCalled jasmine method.
Invoking the functions by itself doesn't make any sense (like in your example)
You should do something like this:
it('All default values', => {
spyOn(class.testFunc);
document.getElementById('Button').click();
expect(class.testFunc).toHaveBeenCalled();
}));
})

Do you need spies to test if a function has been called in Jasmine?

Am learning Jasmine, wondering if the following test would be valid? And if not, can someone explain why? I've been reading a number of tutorials and can't find a good explanation that has helped me understand why I can't seem to write a test like the one below correctly.
// spec
describe("when cart is clicked", function() {
it("should call the populateNotes function", function() {
$("#show-cart").click()
expect(populateNotes()).toHaveBeenCalled();
})
})
// code
$("#show-cart").click(function() {
populateNotes();
})
You need to do two things, first you need to spy on the function before the click. Normally you would spy on a function like this that is a member of an object. Where is populateNotes defined? You need a reference to it somehow.
// This might work, if the function is defined globally.
spyOn(window, 'populateNotes');
// Then do your action that should result in that func being called
$("#show-cart").click();
// Then your expectation. The expectation should be on the function
// itself, not on the result. So no parens.
expect(window.populateNotes).toHaveBeenCalled();

Jasmine junit testing of delegate callback of function args

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

Why do I have to call spyOn in a beforeEach()?

I have a simple test suite that has one it function inside of it. I want to see if a certain function is called within the function I'm calling, so I have something like this:
describe("doStuff", function () {
var foo = new Foo();
spyOn(foo, "doOtherStuff");
foo.doStuff(true);
it("should do stuff and other stuff", function() {
expect(foo.stuffDone).toBe(true);
expect(foo.doOtherStuff).toHaveBeenCalled();
});
});
However, this gives me the error: Expected a spy, but got Function.
After looking around some, I saw all examples had the spyOn in a beforeEach. So, I changed my test to:
describe("doStuff", function () {
var foo = new Foo();
beforeEach(function() {
spyOn(foo, "doOtherStuff");
foo.doStuff(true);
});
it("should do stuff and other stuff", function() {
expect(foo.stuffDone).toBe(true);
expect(foo.doOtherStuff).toHaveBeenCalled();
});
});
And this works. I'm pretty new to jasmine, so I may just be missing something obvious, but I just want to know why it has to be in a beforeEach for the spyOn to work. It's easy enough to just use the beforeEach, but I want to understand better what is going on. Thanks.
That is simply because Jasmine runs the Specs in a different closure. The describe and it calls only register callbacks that are added to a queue and then executed by Jasmine later. And Jasmine always cleans up the spies ...
But you can also add the spyOn to the it callback.

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