I have the following code:
describe("Player", function() {
var player;
beforeEach(function(){
player = new Player({
name: "Mark"
});
});
it("has a name", function() {
expect(player.name).toEqual("Mark");
});
it("has a score"), function() {
expect(player.score).toEqual(0);
};
});
Jasmine says it's passing 2 specs, even though player.score is undefined
If I do...
it("has a score"), function() {
console.log("hello")
expect(player.score).toEqual(0);
};
I can see the second test is never run. Any ideas why? (this is my first time using Jasmine).
There is a misplaced closing parenthesis in the second spec (it() call). It should read:
it("has a score", function() {
expect(player.score).toEqual(0);
});
I run into this issue a lot: syntax errors in Jasmine specs result in tests not even running, rather than failing as they should. (I believe there may be an outstanding bug against Jasmine for this.)
Related
I've been testing JavaScript code using unit testing frameworks like jasmine and Qunit. But all these testing framework works only at load time, but I want to initiate the test cases at run time, for instance I want to test an object's value on a button click like below test case in Jasmine,
function btnClick() {
var temp++;
describe("Test Suite Inside Button Click", function () {
it("To test true value", function () {
expect(temp).not.toEqual(-1);
});
});
};
How to run the test cases dynamically ?
Here is how you do it.
Invoke the jasmineEnv at run time and run the test
Note that I'm clearing out the reporter div just to clean up the
output- which may not to necessary in your case.
My setTimeout is only to load the div onto the page
See it in action here
var testFunc = function() {
//this is optional- I'm just clearing the reporter out to run it on fiddle.
$('.jasmine_html-reporter').remove();
var jasmineEnv = jasmine.getEnv();
describe('test', function() {
it('sample test', function() {
console.log('test ran');
expect(true).toBe(true);
});
});
jasmineEnv.execute()
}
setTimeout(function() {
$('#myElement').click(testFunc);
}, 0);
Wondering if anyone can help me - I'm trying to test my js using Jasmine (1.3) and I can't figure out the best way to test any method calls inside a .then or a .done method.
example code to explain:
Backbone.View.extend({
myMethod: function () {
this.something.done(function () {
this.doSomethingElse();
}.bind(this));
}
})
I'd like to write a test that check that this.doSomethingElse was called.
I was looking around at jasmine.async and a waitsFor/runs set up but I'm not sure how it fits into external code i.e. I'm not going to call done() inside my actual code to get my test working. Also if I mock out the done method on this.something then I'm not longer testing the actual implementation, right?
I'm just missing how things fit together. If anyone could point me in the right direction I'd really appreciate it!
Update: based on feedback below I've now tried the following
Hey, thanks for the answer - I think maybe I don't have the last part correct - have tried 2 different ways, both initial pass but then fail after a second or 2.
it('calls doSomethingElse on done',function () {
var mockDeferred = $.Deferred();
myView.something = mockDeferred;
spyOn(myView,'doSomethingElse');
mockDeferred.resolve();
waitsFor(function () {
expect(myView.doSomethingElse).toHaveBeenCalled();
});
});
And also:
it('calls doSomethingElse on done',function () {
var mockDeferred = $.Deferred(),
someTrigger = false;
myView.something = mockDeferred;
spyOn(myView,'doSomethingElse');
runs(function () {
mockDeferred.resolve();
someTrigger = true;
});
waitsFor(function () {
someTrigger = true;
});
runs(function () {
expect(myView.doSomethingElse).toHaveBeenCalled();
});
});
In both instances the test will pass originally but then timeout to a failure after a second or 2.
Am I missing something?
To test the example function you described, I would do the following within your test:
Create a new deferred object (I'll call it mockDeferred)
Pass mockDeferred into your code under test so that it is now this.something in your example
Spy on the doSomethingElse function
Call myMethod()
Call resolve() on mockDeferred
Assert that doSomethingElse was called
Edit based on OP's Update:
I don't see anywhere in either of your examples where you are calling myView.myMethod() within your test; make sure you do that. I whipped up an example that you can reference here.
As an aside, I'm surprised the second example you tried passes initially. Maybe because you have some code outside of a runs() block?
Related problem
Spying on a method inside .then and expecting .toHaveBeenCalled fails
Solution:
run test inside fakeAsync and run tick() before the expect
Service:
getFirebaseDoc() {
this.db.firestore.doc('some-doc').get()
.then(this.getFirebaseDocThen)
.catch(this.getFirebaseDocCatch);
}
Unit testing:
it('should call getFirebaseDocThen', fakeAsync(() => { // note `fakeAsync`
spyOn(service, 'getFirebaseDocThen');
spyOn(service.db.firestore, 'doc').and.returnValue({
get: (): any => {
return new Promise((resolve: any, reject: any): any => {
return resolve({ exists: true });
});
},
});
service.getFirebaseDoc();
tick(); // note `tick()`
expect(service.getFirebaseDocThen).toHaveBeenCalled();
}));
It appears that sinon.spy(object, method) is not wrapping my object#method as expected.
(I have an uneasy feeling that I'm seeing the same problem as described here and here, but I don't see why this should be. I've instantiated my object before calling sinon.spy(...), and AFAIK I'm not using any cached objects.)
Here's the complete test file:
var
AmbitParser = require('../lib/parsers/ambit-parser'),
expect = require('chai').expect,
sinon = require('sinon');
describe('AmbitParser', function() {
var ambit_parser = new AmbitParser();
describe('#extractLineItems()', function() {
it('calls extractLineItems once', function(done) {
var spy = sinon.spy(ambit_parser, 'extractLineItems');
ambit_parser.parseBills(function gotBills(err, bills) {
expect(ambit_parser.extractLineItems.callCount).to.equal(1); // => expected undefined to equal 1
expect(spy.callCount).to.equal(1); // => expected 0 to equal 1
done();
});
ambit_parser.extractLineItems.restore();
}); // calls extractLineItems once
}); // #extractLineItems
}); // AmbitParser
The call to expect(ambit_parser.extractLineItems.callCount).to.equal(1); results in 'expected undefined to equal 1' and if I change that to expect(spy.callCount).to.equal(1);, I get 'expected 0 to equal 1'.
Together, this makes me think that the call to sinon.spy(...) is not wrapping the ambit_parser.extractLineItems method as expected, but I can't see why this is the case.
The problem is the placement of the call to restore(): it should not be in the body of the test function. Instead, put it in an after() block.
What's happening is that the restore() method is getting called immediately after the test is started, so by the time the callback is executed, the spied upon method has been restored, so sinon will report that the method has never been called.
The following modifications to the original code will work as expected:
describe('AmbitParser', function() {
var ambit_parser = new AmbitParser();
describe('#extractLineItems()', function() {
before(function() {
sinon.spy(ambit_parser, 'extractLineItems');
});
after(function() {
ambit_parser.extractLineItems.restore();
});
it('calls extractLineItems once', function(done) {
ambit_parser.parseBills(function gotBills(err, bills) {
expect(ambit_parser.extractLineItems.callCount).to.equal(1);
done();
});
}); // calls extractLineItems once
}); // #extractLineItems
}); // AmbitParser
Moral of the story: make sure you call reset() only after any callbacks have completed.
I am fairly new to using mocha and I ran into this bug. Please help me understand this behavior.
'use strict';
var flightMiddlewareMock = require(process.cwd() + '/test/mock/response/flightmock');
describe('Test Flights function: getTime', function(){
var mockData;
beforeEach(function(done){
mockData = flightMiddlewareMock.getValidData();
done();
}
it('getFlightDescription returns the full flight description', function(done){
contentUtils.loadContent({
'files': {
activity: '/flights/america'
},
'locality': "en_US"
}, function(err, bundle) {
var flightsMiddleware = new FlightsMiddleware(country, mockData.req, bundle);
console.log('inside content callback');
description = flightsMiddleware.getFlightDescription(mockData.results.body.items[0]);
assert.equal(description, "Boeing 777");
done();
}
});
});
Output looks like this
inside content callback
inside content callback
inside content callback
- Failure of test!
Question - I do not understand why in spite of using 'use strict' it does not complain about description not being declared.
Please note: If I do modify this to
var description = .....
it works viola! Am I missing something?
Thanks for your time!
Mocha will report the exception caused by trying to assign to an undeclared variable. If I run this:
"use strict";
it("foo", function (done) {
setTimeout(function () {
description = "foo";
done();
}, 1000);
});
I get the result:
1) foo
0 passing (1s)
1 failing
1) foo:
Uncaught ReferenceError: description is not defined
at null._onTimeout (test.js:5:21)
Now, I've used setTimeout which is a well-behaved function in that when the callback passed to it throws an exception, setTimeout does not prevent this exception from reaching the top of execution context. In other words, it does not swallow exceptions.
If you have a callback that throws an exception but this exception is swallowed by the code that called the callback, you'll get a test timeout but you won't know why because Mocha won't be able to detect the exception. It relies on the uncaughtException event, which is not emitted if the exception is swallowed.
When working with Jasmine testing framework, I have come across a code snippet where expect is written in a sub-function which is called in it(), but not in it() itself. The reason behind writing this is, they were trying to compare similar objects and they refactored test code and moved this expect to the sub-function. Now, we don't have expect in it() rather we have a method call which has expect.
describe("bla bla", function() { //for nunit, junit guys, this is testSuite()
function somefunc() { //this is [test]
//do some stuff and generate object
expect(someObject).toEqual(otherObject); //expect is assert
}
it("some case", function() {
//do some stuff
somefunc();
});
it("some other case", function() {
//do some other stuff
somefunc();
});
});
Now, is this kind of test code encouragable? can we have it() without expect ?
I would argue that the two examples below are both readable. If assertExpected() did some kind of setup for otherObject the first example could be more readable.
describe("bla bla", function() { //for nunit, junit guys, this is testSuite()
function assertExpected() { //this is [test]
//do some stuff and generate object
expect(someObject).toEqual(otherObject); //expect is assert
}
it("some case", function() {
// Arrange
var someObject;
// Act
someObject = testMethod('foo');
// Assert
assertExpected();
});
it("some other case", function() {
// Arrange
var otherObject, someObject = testMethod('foo');
// Act
someObject = testMethod('foo');
// Assert
assert(someObject(foo)).toEqual(otherObject);
});
});
I think the deciding factor here should be deciding on a house style and sticking with it. There's no clear winner here and this question probably isn't a good question for SO.