Javascript Unit testing and refactoring (using Angular js framework) - javascript

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.

Related

Understanding state in jest tests that use spyOn

Suppose that I have a test file foo.test.ts that looks like this:
describe("foo", function() {
let myMock;
beforeAll(function() {
myMock = jest.spyOn(someObject, "someMethod");
});
test("my test", function() {
beforeEach(function() {
myMock.mockReturnValue("someValue");
});
...
});
afterAll(function() {
myMock.mockRestore();
});
});
I'm using this pattern because I've seen it recommended in other StackOverflow answers. I wish to understand how Jest works though.
Do I really need to store the mock in a variable, or can I do this?
describe("foo", function() {
test("my test", function() {
beforeEach(function() {
jest.spyOn(someObject, "someMethod").mockReturnValueOnce("someValue");
});
...
});
});
Notice that I'm using mockReturnValueOnce instead of mockReturnValue.
I ran both implementations and they work fine, but I wonder whether I can say that they are equivalent? Will the "someMethod" function, part of "someObject", not be retained as a mock across other tests from other files?
jest.spyOn() returns a jest mock function and you want to store the returned mock function in a variable so that you can make assertions.
If you don't store the mock function returned by jest.mock(), then how will you make assertions? All the methods, provided by jest, that can be called on a mock function, can't be called without having a reference to the mock function.
If you just want to mock a return value and not make any assertions on the mocked function, then you don't need to save the reference. Generally, when you mock a function, you want to make assertions like how many times it was called, what arguments it was called with, etc.
Will the "someMethod" function, part of "someObject", not be retained
as a mock across other tests from other files?
someMethod will only be mocked in the test file where you mock it. It won't affect the other test files.

JQuery Unit Testing tooltips (jasmine, qunit, etc..)

I was wondering if anyone could provide me information, perhaps some example code, on how to unit test tooltips?
The framework is no issue, I am free to use any kind of Javascript/JQuery framework there is available (Jasmine, Qunit etc).
The hard part is that I can not really find a good example of how tooltips (which their scripts is called asynchronously) are tested.
So any example regarding unit testing JQuery UI tooltip or other external libraries (qtip etc) would be really helpfull.
The jQuery team uses Qunit for their testing. When I work on jQuery plugins, I tend to use the same tools. Here is an example test in Qunit:
//In your JS
function myTestFunction() {
//code here
}
//In test.js
QUnit.test( 'My Tests: ', function( assert ) {
'use strict';
var $el = $('#my-tooltip');
assert.strictEqual( typeof myFunction, 'function', 'It is a function.' );
assert.notEqual( $el.css('display'), 'none', 'It is visible.' );
});
Jasmine supports asynchronous tests in general. You can make your assertions in a callback and call done() to signify that your test successfully completed.
For example
it("should work with async", function(done) {
doSomethingAsync().success(function() {
// make assertions in callback
done(); // done with test
});
})

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

Ember Data's store promises don't work in quint tests

Update
A bit of context into some quirks of the illustrative code below. StoreProxy exists as a model, created by the ApplicationRouter, that has a reference to the store. This lets other objects access the store directly (for singletons, tests, etc). Example:
MyApp.StoreProxy = DS.Model.extend();
MyApp.ApplicationRoute = U.Route.extend({
model: function () {
return this.store.createRecord('storeProxy');
}
});
Before the route is executed, StoreProxy doesn't have a store property. After, it does. I can only assume this is because of some ember-data magic.
I very well realize your reaction to this may be "Ugh! No! You're doing it wrong!". Noted. We'll move to do it the right way from here over time. That said, this is where the code is now. So, given that, and given this method for getting a reference to the current store, why doesn't the code below call its accept or rejection handlers?
Original question
I'm writing a qUnit unit test for ember. I'm using fixture data. The findAll call on the store isn't resolving or rejecting the promise.
test('Find all in store', function() {
expect(1);
var findPromise;
findPromise = MyApp.StoreProxy.store.findAll('rule');
findPromise.then(function(result) {
console.log('yes');
ok(true);
}, function(error) {
console.log('no');
});
});
I tried using async tests mentioned in this question:
testing ember fixture data with quint but the resolve and reject are never called, so the test hangs indefinitely.
I've also tried placing Ember.run calls around my code, in case it's a weird run loop thing. But to no avail.
asyncTest('Find all in store', 1, function() {
var findPromise;
Ember.run(function() {
findPromise = MyApp.StoreProxy.store.findAll('rule');
findPromise.then(function(result) {
console.log('yes');
ok(true);
start();
}, function(error) {
console.log('no');
start();
});
});
});
The code I'm testing runs fine when I run the application normally (fixture adapter or no), so it feels like something with the test environment.
Any thoughts on what to try? I'm stumped.
The way that you're writing your asynchronous tests is incorrect. Check out QUnit's page on async testing. Your test should look something like this:
asyncTest('Find all in store', function() {
var findPromise = ...;
findPromise.then(function(result) {
start();
ok(result);
}, function() {
start();
ok(false);
});
});
Specifically:
You put an extra parameter in the asyncTest function, which likely causes the test to not run at all.
You're using Ember.Application.store, which is not how you should access your store (and probably isn't even a valid store). I'm not sure what your context is, but you should be getting your store from elsewhere.
You're putting the start() calls after your assertions when they should be before.

unit testing in javascript: how do you mock? - a (hard for me) example

I just rewrote backbone-mongodb to be really compatible with backbone. The original solution had nice vows for testing, and I would like my code to get tested as well, but simply have no idea how to do it.
Here is an example, I would like to test:
update: function(callback) {
var model = this.model;
this._withCollection(function(err, collection) {
if (err) callback(err);
else {
var attributes = _.clone(model.attributes);
delete attributes['_id'];
collection.update({ _id: new ObjectID(model.id) }, {$set: attributes}, {safe:true, upsert:false}, function(err) {
model.fetch();
callback(null, model.toJSON());
});
}
});
},
This code has nothing special in it. It uses the node-mongodb-native driver, and updates a record in the database. AFAIK, proper testing would mean to at least check that (1) collection.update was called with the given arguments, (2) callback is called when and how it should be, (3) model contains the new data.
With vows I can check (2), but have no idea at all how to check (1). Actually, the same holds for every unit testing framework I know about, qUnit, Jasmine. I'm sure that this can be done somehow, and I'm decided to learn at least one of them, but it's hard to make a choice when you got stuck at the beginning. :)
I know about sinon.js and think that everyting can be tested using mocking all the objects I have until I end up having the collection mocked as well, but this seems to be extremely clumsy. Could someone help me in writing the above tests please, and I'll happy to write out a tutorial of it?
I will use Jasmine for that purpose; I don't how familiar are you using that library, but they have a plugin to use jQuery for writing spec tests, you can load fixtures/templates and run tests on it.
for your particular case, assuming that function is part of MyObj "class", I will write something like:
describe("My object tests", function() {
it("Should update my obj", function () {
var noError, flag = false;
MyObj.update(function (err, model){
flag=true;
noError= err==null;
// or you can do other checks on the result
})
// we wait for 5 sec until get a response (flag==true)
waitsFor(function (){ return flag}, "Timeout on update", 5000);
// check if there are no errors
expect(noError).toBeTruthy();
});
});

Categories