Jasmine Testing toEqual is correct value, still failing test - javascript

I am writing a series of tests to demonstrate the value of 'this' in different contexts.
Here is my current Test suite:
describe("this keyword", function(){
it('returns the global context of this', function(){
expect(globalThis()).toEqual(window);
});
it('returns the method context of this', function(){
expect(methodThis.showThis()).toEqual({ showThis : Function });
});
});
My second test won't pass with this code even though it is the exact value:
var methodThis = {
showThis: function(){
return this;
}
};
All this function is doing is returning the context of this inside of an object.
Why is this test failing even though the correct toEqual value is being passed to toEqual?

You can use jasmine.any for comparing the function type:
describe("this keyword", function(){
it('returns the method context of this', function(){
expect(methodThis.showThis()).toEqual({ showThis : jasmine.any(Function) });
});
});

Related

Writing JavaScript tests that test other functions are called, without actually calling them

I have been tasked with writing unit tests for some AngularJS code that was written by another team, who didn't write any tests
They have written the following function but I cannot figure out how to test it
function showCallAlerts(callRecord, isInEditMode, callBack) {
var callAlerts = populateCallAlertOnEditCall(callRecord.callAlert);
var callModalInstance = openAlertModalInstance('Call', callAlerts, callBack);
if (callModalInstance !== undefined && callModalInstance !== null) {
callModalInstance.result.then(function() {
// Show equipment alerts based on company details
showEquipmentAlertsBasedOnCompanyDetails(callRecord, isInEditMode, callBack);
});
} else {
// Show equipment alerts based on company details
showEquipmentAlertsBasedOnCompanyDetails(callRecord, isInEditMode, callBack);
}
}
I need to test that each of the functions are called, not worrying about what they do as I'll test them separate, just that they are called.
When populateCallAlertOnEditCall is called it needs to either return an empty array or an array with some items in it
When openAlertModalInstance is called it needs to either return undefined or something that passes through to showEquipmentAlertsBasedOnCompanyDetails
showEquipmentAlertsBasedOnCompanyDetails should actually be called, I'll test that method separate, just that it was called
I have manged to write code to test simple functions but nothing like this one so any help will be much appreciated, I spent most of this afternoon trying to figure it out
You can use jasmine to mock the function calls that you are not interested in testing. For example, you can tell jasmine to return an empty array every time 'populateCallAlertOnEditCall' is called. I will write an example that might give you an insight:
describe('My Test Spec', function() {
var myController;
...
beforeEach( inject(($controller) => {
myController = $controller("myControllerName");
}));
it('Testing showCallAlerts when populateCallAlertOnEditCall returns an empty array', inject(function($controller) {
//setup
//this will replace every call to populateCallAlertOnEditCall with
//the function inside callFake
spyOn(myController, 'populateCallAlertOnEditCall ').and.callFake(function() {
return []; //returning an empty array.
});
//action
myController.showCallAlerts(...);
//assert
//Do your checking here.
}));
it('Testing showCallAlerts when populateCallAlertOnEditCall returns a non-empty array', inject(function($controller) {
//setup
//this will replace every call to populateCallAlertOnEditCall with
//the function inside callFake
spyOn(myController, 'populateCallAlertOnEditCall ').and.callFake(function() {
return [1,2,3,4]; //returning a non-empty array.
});
//action
myController.showCallAlerts(...);
//assert
//Do your checking here.
}));
});
the test that something has been called, you can use a Spy
your assertion would look like:
spyOn(obj, 'populateCallAlertOnEditCall')
expect(obj.method).toHaveBeenCalled()
UPDATED:
populateCallAlertOnEditCall = {}
spyOn(obj, 'populateCallAlertOnEditCall.result')
expect(obj.method).toHaveBeenCalled()
The kind of behaviour you want is called mocking
In Jasmine, mocking is done with Spy Objects, you can read more about those here
Basically, you can use mocks to test if functions were called with the expected parameters.
var xhr = mock( XMLHttpRequest );
xhr.send();
expect( xhr.send ).toHaveBeenCalled();

jasmine mock second method

I am trying to do the following thing in Jasmine but not sure if it is possible :
I Got a service object with 2 methods, A and B.
Method A calls method B (B is in fact a $http call which I do not want to do during my test : I want to mock it).
In my BeforeEach section I do this :
spyOn(Serviceinstance, 'B').and.callFake(function(){
return true;
});
in my Test :
var result = Serviceinstance.A();
expect(result).toBeTrue();
Of course, the real code of B returns false.
My problem is that my test always fails. the function provided in the spy is never called by method A.
On the other hand, If I call B like this :
var result = Serviceinstance.B();
Then the function of the spy is called, and my test passes.
So should I modify my instance like this :
Serviceinstance.B = function(){return true;}
because Jasmine cannot mock a "second" level of the call stack ? (seems totally unlikely to me)
I am definitively missing something....
This is a code that works:
describe('Service test suite', function() {
it('should return true', function() {
var Serviceinstance = new Service();
spyOn(Serviceinstance, 'B').and.callFake(function() {
return true;
});
expect(Serviceinstance.A()).toBe(true);
})
});
https://jsfiddle.net/ronapelbaum/9moLhhbr/

mocha nesting/replicating tests

Given a data structure that satisfies some invariants, I would like to test the state of an instance of the data structure after various operations. What is the best way to do this?
describe('data-structure', function() {
var x;
beforeEach(function() {
x = getDataStructure();
});
describe('satisfies invariants', function() {
// run tests on 'fresh' x
it('should ...', function() {
// ...
});
// ...
});
describe('operation 1', function() {
it('should preserve invariants', function() {
x.doSomething();
// run 'satisfies invariants' tests on modified x
});
});
});
I thought about using an afterEach hook, but I do not think x is preserved there?
afterEach(function() {
// somehow run 'satisfies invariants' test
});
It maybe be that I can refactor 'satisfies invariants' into a method, but it would be nice if mocha could report which invariant-tests failed for each operation, e.g.
data-structure
satisfies invariants
should satisfy invariant 1 ...
...
operation 1
should satisfy invariant 1 ...
...
operation 2
should satisfy invariant 1 ...
...
Edit
Using the structure
describe('data-structure', function() {
var x;
describe('satisfies invariants', function() {
afterEach(function() {
it('should satisfy invariant 1', function() {
// x.value === a again
// ...
});
// ...
});
it('should work after operation 1', function() {
x = getDataStructure(); // x.value === a
x.operation1(); // x.value === b
});
it('should work after operation 2', function() {
x = getDataStructure();
x.operation2();
});
// ...
});
});
does not seem to preserve the changes to x.
It follows an example, let me know if I forget something of what we have discussed:
var assert = require('assert');
describe('data-structure', function() {
var x;
beforeEach(function() {
// freshly created data structure for each describe block below
x = getDataStructure;
});
describe('satisfies invariants', function() {
after(function() {
// it executes those tests only once after all the it block below
assert(x); // put your tests here
});
it('op 1.1', function() {
do_something_on(x);
});
it('op 1.2', function() {
// keep in mind that x is the same instance of the previous test
do_something_else_on(x);
});
// so on
});
describe('satisfies something else', function() {
// here you have a new instance of x, because of the outer beforeeach
after(function() {
// it executes those tests only once after all the it block within this describe block
assert(x); // put your tests here
});
it('op 2.1', function() {
do_something_on(x);
});
it('op 2.2', function() {
// keep in mind that x is the same instance of the previous test, but not the one used in 1.2
do_something_else_on(x);
});
// so on
});
// so on
});
This piece of code should give you an idea of which instance is accessible and where.
If it lacks something, let me know and I'll have a go to fix it.
The Problem
Mocha does not support putting it inside a hook like you do in your last snippet. (afterEach is a hook). In some trivial cases you may get the desired behavior but that's just luck. Once you move on to more complicated test suites, you won't get the behavior your expect.
Moreover, I suggest that afterEach is the wrong place for that kind of test. You should use the hooks only to setup and tear down your test environment and not for performing assertions on the state of your code. Mocha treats any failure in a hook as "the test suite is broken, abort!!" rather than as a test failure. Look at this example, for instance:
var assert = require('assert');
describe("test", function () {
var x;
beforeEach(function () {
x = { foo: 'something' };
});
afterEach(function () {
assert(x.foo === 'something');
});
it("one", function () {});
it("two", function () {
x.foo = 'something else';
});
it("three", function () {});
});
In theory there's no reason test three should not run but when the failure occurs in the afterEach hook after test two is run, Mocha will just stop running tests there. The output (omitting the final stack trace) is:
test
✓ one
✓ two
1) "after each" hook
2 passing (14ms)
1 failing
Note how two is marked as passing but the hook failed. And note how three is never even attempted. As soon as there is a failure in a hook, Mocha stops right there.
The Solution
You should just create a function that you call from each test to test your invariants. For instance:
var assert = require('assert');
describe("test", function () {
var x;
beforeEach(function () {
x = { foo: 'something' };
});
function testInvariant() {
assert(x.foo === 'something');
}
it("one", function () {
testInvariant();
});
it("two", function () {
x.foo = 'something else';
testInvariant();
});
it("three", function () {
testInvariant();
});
});
If you run Mocha on the code above, you'll get (again, omitting the final stack trace):
test
✓ one
1) two
✓ three
2 passing (10ms)
1 failing
two was marked as failed and Mocha moved on to run three, which was successful.
If you don't want to write testInvariant() in each test you could create a function that adds it for you. For instance:
var assert = require('assert');
describe("test", function () {
var x;
beforeEach(function () {
x = { foo: 'something' };
});
function makeTest(name, fn) {
it(name, function () {
fn();
assert(x.foo === 'something');
});
}
makeTest("one", function () {
});
makeTest("two", function () {
x.foo = 'something else';
});
makeTest("three", function () {
});
});
This produces the same output as the previous code snippet.

Calling and Testing Meteor Methods with Mocha

I am looking for a solution to test Meteor Methods with mocha. I am using Velocity and the Mocha package.
This is an example method I am trying to test.
Meteor.methods({
addPoints: function(userId, points) {
return Players.update(userId, { $inc: { score: +points } });
}
});
This is, in a round about way how I would call it using node, I want to call the methods with arguments and assert that in this case, it returns 1 for updating the mongo document
if (!(typeof MochaWeb === 'undefined')){
MochaWeb.testOnly(function(){
describe("Meteor Method: Upldating a player", function(){
// define the handler as the method we are testing
// May be this needs to be a before each.
var handler = Meteor.call("addPoints");
var userId = "1";
var points = 5;
describe("Updating a player", function() {
it("Should Add a point", function(done){
handler(userId, points, function() {
assert(handler.calledOnce);
// a way here of asserting the callback is what we expect,
// in this case we expect a return of 1
done();
});
});
});
});
});
}
Thanks
Assuming your tests run on the server, you should avoid sending a callback to the method call. This way, the Meteor method will run "synchronously" (in the fibers sense).
I would re-write the describe section as follows:
describe('Updating a player', function () {
beforeEach(function() {
handler(userId, points)
})
it('Should Add a point', function () {
assert(handler.calledOnce)
})
})

jasmine Expected spy myLinks to have been called error

I am having a hard time understanding jasmine spyOn function.
I wrote a simple function and test if my method was called:
function myView() {
myLinks();
}
Here are my tests:
describe('#myView', function() {
it('updates link', function() {
var spyEvent = spyOn(window, 'myLinks');
expect(spyEvent).toHaveBeenCalled();
});
});
This returns the following failure:
Expected spy myLinks to have been called
What am i doing wrong here?
You need to call the myView() function so the myLinks() have been called.
function myLinks(){
//some tasks
}
function myView() {
myLinks();
}
This two function above are declared in window object, then you create a spy object pointing to the window.
describe('#myView', function() {
myView();//Call the method so the myLinks was called too
it('updates link', function() {
var spyEvent = spyOn(window, 'myLinks');
expect(spyEvent).toHaveBeenCalled();
});
});

Categories