How to setup namespaces in Jasmine for testing? - javascript

I need to add functionality to a Javascript class that I want to test using Jasmine. The class definition goes something like this:
GAME.Player.CustomPlayerSetup = function() {
...
};
If I remove GAME.Player I can write normal tests and have them pass. But when try to leave Game.Player in the class definition for CustomPlayerSetup, I get a Reference Error Game is not defined. How do define this test?
To answer Charles' suggestion, even if I declare the GAME and Player vars in my Jasmine test file before the the require line it still gives me, as in
GAME = {};
GAME.Player = {};
CustomPlayerSetup = require("../CustomPlayerSetup").CustomPlayerSetup;
describe("Custom Player Setup", function() {
...
});
the same error which points to the production code file, and not the test file. I'm using jasmine-node to run the tests.

Most likely in your spec-runner you have whatever file instantiates Game and/or player below the file running the spec (or you didn't include it at all).
If that's not the case try posting your spec-runner as well as one of your tests that fails.

Looks to me, you need to instantiate the object GAME.Player before run/include the js file on your jasmine tests. something like:
<script type="text/javascript">
var GAME = {Player:{}};
</script>
</script src="your_src.js"/>

Related

How do I mock out objects used in the constructor in JavaScript?

I have some legacy JavaScript code that I am trying to write some unit tests for - I use Jasmine for that. The classes looks like the below example. Some public methods, but also with some code which gets executed when the file is loaded - I guess it could be considered the constructor of the class.
var Overview = (function(){
HubStarter.wait("Overview");
var exports = {};
exports.Format = function(value){
//some code
};
return exports;
})();
When I run the tests in Visual Studio with ReSharper, I get no errors. But when I run the tests with Karma I get some errors because of some code is being run when the JavaScript file is loaded - the code calls some methods on undefined objects.
I have no problem testing the Format method on the Overview object, but HubStarter is undefined. I haven't added the HubStarter.js file to karma.conf.js because that file is dependent on a lot of other things.
Is there any way to mock out the HubStarter object when it is being called so early in the execution?

Test driven node (without testing frameworks)

I have my code:
var User = function() {
...
}
and the test code using IIFE:
(function() { // test new user
var user = new User();
if (typeof user === 'undefined') {
console.log("Error: user undefined");
}
...
}());
both in the same js file. Works great! But, as the program grows, this is becoming too refractory for me to manage, as I have a piece of test code for every piece of business logic.
I've been taught to keep all my js in the same file, (minified is good) in production, but is there a best-practical way to keep my test code in a different file during development?
I was thinking I could use a shell script to append the test code to the production code when I want to run the tests, but I'd prefer a cross-platform solution.
I don't want or need a framework solution, I want to keep it light -- does node have anything built-in for this sort of thing?
Node has two expressions for this case. First:
module.exports = name_of_module;
Which is to export module for example function, object or something similar. And the second:
var module_name = require('Path/to/module');
to import it from other file. If you want to export IIFE you must assign it to global variable and module.export name of variable.

Javascript Jasmine Testing: Prevent tested function to call function from object that was created within tested function

I want to test a Javascript function with Jasmine that has a structure like this:
showEditUser: function (...) {
// more code here...
var editUserView = new EditUserView();
// more code here...
editUserView.generate(...);
}
editUserView.generate() causes an error. That does not matter because I don't want to test it. But how can I prevent it from being called?
EditUserView is a RequireJS Module that extends another Module called BaseView. The function generate() is defined in BaseView. There are other Modules that extend BaseView and I want all of them not to call generate while testing. How can I do that with Jasmine? It seems not to be possible with spyOn(...).and.callFake() because I don't have the editUserView Object when calling the function. Is there kind of a static way to tell Jasmine to callFake() the function generate in BaseView?
There is no "nice" way to solve this with jasmine. I think, to take a BaseView viewObj as parameter is a nicer coding style. It will reduce the dependencies of the method. So it don't have to know the specific BaseView-class, he will simply need a viewObj that has a generate-method.
showEditUser: function(..., viewObj) {
// ...
viewObj.generate(...);
}
Then you could create a ViewMock and put it into that function like this:
var viewMock = {};
viewMock.generate = jasmine.createSpy('generate() spy');
Then you will call it this way:
showEditUser(..., viewMock);
EDIT: Here is a similar question

How To Test a Grunt Plugin

I'm creating my first ever Grunt Plugin. I would really like to practice testing my plugin as I develop. I've selected mocha as my testing framework, as it seems popular, and setup my gruntfile to automatically watch when test files are altered and run them. This all looks good.
But, I've not found a lot of documentation on how to actually test a Grunt Plugin. I've looked at code of about a dozen different grunt plugins, especially the contrib ones, and they don't make a lot of sense to me.
As I try to test my code I'm trying to break things down into very specific functions. So, here is the basic structure of a plugin, with a function in it.
'use strict';
function testOutsideOfTask(){
return "i am outside";
}
module.exports = function(grunt) {
grunt.registerMultiTask('example_task', 'I do a thing.', function() {
function testInsideOfTask(){
return "i am inside";
}
});
};
I've included a couple of methods just explicitly to make sure my testing is working, and it's not. Neither of these methods seem to be accessible... How could I access both of them for testing? Here is the mocha test as I have it.
var grunt = require('grunt');
var assert = require("assert");
describe('testOutsideOfTask', function() {
it('do something', function() {
assert.equal("i am outside", testOutsideOfTask());
});
});
describe('testInsideOfTask', function() {
it('do something', function() {
assert.equal("i am inside", testInsideOfTask());
});
});
They both return something like this. So, somehow it just can't access the functions, however, when I look at other testing examples, they don't seem to specifically require the file that is being tested... For example https://github.com/gruntjs/grunt-contrib-clean/blob/master/test/clean_test.js
1) testOutsideOfTask should do something:
ReferenceError: testOutsideOfTask is not defined
Thanks very much!
You want to be testing functionality, ideally. Your Grunt plugin should end up as a wrapper around more abstract methods that do what you want but not necessarily tied to how Grunt works; then for the actual plugin you run those methods on each file, log some output etc. Something like this:
var lib = require('./lib.js');
module.exports = function(grunt) {
grunt.registerMultiTask('test', function() {
lib.doSomeMethod();
grunt.log.ok('Something happened');
});
}
So in that pseudo code you would want to actually test the doSomeMethod function and not that Grunt registered a task or logged to the CLI. That's already well tested.
A lot of Grunt plugins work in this way, in fact many are wrappers around existing node modules. For example, grunt-recess is a wrapper of twitter/recess:
https://github.com/sindresorhus/grunt-recess
https://github.com/twitter/recess
One of my own modules is more Grunt specific, but the tests for that focus on the actual functionality of the module. You can have a look at that here:
https://github.com/ben-eb/grunt-available-tasks/blob/master/test/lib/filterTasks.test.js
I'm also testing with Mocha. I'd recommend that you use grunt-mocha-test to run your tests through Grunt (as well as JSHint and others).

Reset closure variables for unit testing in Javascript

I have the following module in Javascript
var module = (function (){
var cache = {};
return {
postMessage: function (msg){
if(!cache[msg]){
cache[msg] = true;
console.log(msg);
}
}
}
}());
When I write unit tests in Jasmine for this module I would like to have a clean module with an empty cache variable at the beginning of each test. I can't find a solution for this problem except for a helper function that clears the cache and that is publicly available.
Is there a way to clear closure variables for unit testing? I don't need a solution for production code, because in case I would like to clear in production I would have such a helper function anyways.
There is no way to reset the cache in your case. What you have here is a Singleton with a private state, so your lost, cause you can't reset the state and you cant create a new instance of module in your test.

Categories

Resources