Unable to use inject from angular mocks - javascript

I am working on an AngularJS app. One of my services is really buggy. For that reason, I want to test it. To run those tests, I wanted to use a grunt task. The idea is, I would type grunt test from the command line to run my unit tests. My first step was creating my grunt file, which looks like this:
gruntfile.js
'use strict';
module.exports = function (grunt) {
grunt.initConfig({
jasmine: {
mocks: {
src: 'dist/service.min.js',
options: {
specs: 'test/*.js',
vendor: [
'bower_components/angularjs/angular.min.js',
'bower_components/angular-mocks/angular-mocks.js'
]
}
}
}
});
require('load-grunt-tasks')(grunt);
grunt.registerTask('test', ['jasmine:unitTests']);
};
Then, my tests would look like this:
service.spec.js
describe('myModule', function() {
beforeEach(function() {
module('myModule');
});
describe('$myService', function () {
var service = null;
beforeEach(inject(function ($myService) {
service = $myService;
}));
it('should get here', function () {
console.log('first test');
var isSynchronized = service.isSynchronized();
expect(isSynchronized).toBe(true);
});
});
})
This test is intended to test my service:
service.js
'use strict';
angular.module('myModule', [])
.factory('$myService', [function () {
return {
isSynchronized: function () {
return true;
}
};
}]
);
My problem has to do with the inject command in the tests. That function call causes the test to break. If I remove the beforeEach block that uses inject, the test at least runs. I keep hearing about Karma. However, I don't know much about it.
Is Karma a required piece to test AngularJS services? I can't find an example of testing an ngularJS service from grunt. Everything I see is in the browser. I'm trying to create the minimum required grunt file that will allow me to test my AngularJS service. However, I'm totally stuck. I can't figure out why inject is failing.
Can someone please tell me what I'm missing. Or, perhaps point me to an example that uses grunt to test an AngularJS service? Currently, I see the following in the command line, so I know service.js exists.
Running "uglify:mocks" (uglify) task
Verifying property uglify.mocks exists in config...OK
Files: dist/service.js -> dist/service.min.js
Options: banner="", footer="", compress, mangle={}, beautify=false, report="min", expression=false, preserveComments=false
Minifying with UglifyJS...Reading dist/service.js...OK
OK
Writing dist/service.min.js...OK
File dist/service.min.js created: 293 B → 190 B
Running "jasmine:mocks" (jasmine) task
Verifying property jasmine.mocks exists in config...OK
Files: dist/service.min.js
Options: version="2.0.1", timeout=10000, styles=[], specs="test/*.js", helpers=[], vendor=["bower_components/angularjs/angular.min.js","bower_components/angular
-mocks/angular-mocks.js"], outfile="_SpecRunner.html", host="", template="C:\\source\\myModule\\node_modules\\grunt-contrib-jasmine\\tasks/jasmine
/templates/DefaultRunner.tmpl", templateOptions={}, junit={}, ignoreEmpty=false, display="full", summary=false
Reading C:\source\myModule\node_modules\grunt-contrib-jasmine\tasks\lib/../jasmine/reporters/PhantomReporter.js...OK
Writing .grunt\grunt-contrib-jasmine\reporter.js...OK
Reading C:\source\myModule\node_modules\grunt-contrib-jasmine\tasks\lib/../../vendor/jasmine-2.0.1/jasmine.css...OK
Writing .grunt\grunt-contrib-jasmine\jasmine.css...OK
Reading C:\source\myModule\node_modules\grunt-contrib-jasmine\tasks\lib/../../vendor/jasmine-2.0.1/jasmine.js...OK
Writing .grunt\grunt-contrib-jasmine\jasmine.js...OK
Reading C:\source\myModule\node_modules\grunt-contrib-jasmine\tasks\lib/../../vendor/jasmine-2.0.1/jasmine-html.js...OK
Writing .grunt\grunt-contrib-jasmine\jasmine-html.js...OK
Reading C:\source\myModule\node_modules\grunt-contrib-jasmine\tasks\lib/../../vendor/jasmine-2.0.1/boot.js...OK
Writing .grunt\grunt-contrib-jasmine\boot.js...OK
Reading C:\source\myModule\node_modules\grunt-contrib-jasmine\tasks\lib/../../vendor/jasmine-2.0.1/jasmine_favicon.png...OK
Writing .grunt\grunt-contrib-jasmine\jasmine_favicon.png...OK
Reading C:\source\myModule\node_modules\grunt-contrib-jasmine\tasks\lib/../../node_modules/es5-shim/es5-shim.js...OK
Writing .grunt\grunt-contrib-jasmine\es5-shim.js...OK
Reading C:\source\myModule\node_modules\grunt-contrib-jasmine\tasks/jasmine/templates/DefaultRunner.tmpl...OK
Processing source...OK
Writing _SpecRunner.html...OK
Testing jasmine specs via phantom
Thank you!

Related

Karma: Angular Module Mocking

I am currently trying to write karma unit tests for a controller in an angular app. For me the desired result is to load ONLY the controller which I am testing (assume for now I only ever want to test this one controller) and have all other dependencies mocked out for me.
To set the stage:
I have a module: 'XYZ' defined in js/xyz_module.js
I have a module: 'ABC' defined in js/abc_module.js
module 'ABC' is dependent on 'XYZ'
module 'ABC' has a controller: 'AbcController' defined in js/abc_controller.js
my testing is to be done ONLY on 'AbcController'
karma.conf.js:
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'js/abc_module.js',
'js/controllers/abc_controller.js',
'spec/karma/abc_controller_spec.js'
],
...
abc_module.js:
angular.module('ABC', ['XYZ']);
abc_controller.js:
angular.module('ABC').controller('AbcController', ['$scope', function($scope) {
$scope.letters = ['a', 'b', 'c']
}]);
abc_controller_spec.js:
describe('AbcController', function() {
beforeEach(function() {
angular.mock.module('XYZ');
module('ABC')
});
var $controller;
beforeEach(inject(function(_$controller_) {
$controller = _$controller_
}));
describe('$scope.letters', function() {
it("is set to three letters", function() {
var $scope = {};
$controller('AbcController', {$scope: $scope});
expect($scope.letters.length).toEqual(3)
})
})
});
My theory was that, since module XYZ is a mocked module that I should NOT have to include js/xyz_module.js in my karam.conf.js file, but that the mocking framework would simply mock it for me. Unfortunately this does not seem to be the case. When I run karma I get an error that it cannot find the module 'XYZ'. Is there any way around this? If I have to include all dependencies even to test a portion of an application, it will make it exponentially more difficult with more complex applications. Obviously this is a contrived example and the project I am actually working with involves many modules with many dependencies, making it exceedingly difficult to test portions of it if I have to effectively include the whole application. I thought that was the whole point of mocking? Am I missing something?
After further research I think I now realise that angular.mock.module does not actually CREATE a module but is used to initialise an existing module. As such, if I create an additional mock file with: angular.module('XYZ',[]);, add it to karma.conf.js and THEN do beforeEach(angular.mock.module('XYZ')); that seems to work. One baby step forward. The next step is mocking any dependencies that 'XYZ' has and that my 'ABC' module uses, but that is probably another question.

Using Jasmine Ajax

I am writing some tests with Jasmine. I am running those tests via Gulp. I want to use the Jasmine Ajax plugin. However, I cannot figure out how to include it into my tests. Right now, I have the following:
tests.js
describe('MyApp', function() {
beforeEach(function() {
jasmine.Ajax.install();
});
it('should run an ajax request', function() {
// test ajax
});
});
Once again, I'm running this via Gulp. So, in my gulpfile.js I have the following:
gulpfile.js
var gulp = require('gulp');
var jasmine = require('gulp-jasmine');
gulp.task('test', function() {
return gulp
.src('tests/*.js')
.pipe(jasmine());
});
When I execute this, I get the following from the command-line:
TypeError: Cannot read property 'install' of undefined.
Its like Jasmine Ajax isn't getting loaded. Yet, I'm not sure how to load it. Can someone please help me solve this issue?
Thank you.
I haven't tested this myself since I don't have enough info to recreate your setup, but you could try to put the mock-ajax.js file in the helpers directory, that is where the default configuration of jasmine-npm, which is used by gulp-jasmine, looks for them.

ReferenceError: Can't find variable: define at ... with 'grunt test' using jasmine in require.js

I'm a little confused. In my little project I'm using Jasmine, Require.js, Phantomjs and Grunt (all these via Yeoman). So when run I grunt test in the terminal, I get the error:
>> ReferenceError: Can't find variable: define at
>> test/spec/testSpec.js:15
Warning: No specs executed, is there a configuration error? Use --force to continue.
Aborted due to warnings.
But when I perform the test in a browser, the test goes fine...
Here's my simple test spec:
define(['spec/test'], function(Test) {
describe('Test for unit-test', function() {
describe('Test namespace', function() {
it('should be defined', function() {
expect(Test).toBeDefined();
});
});
});
});
Module:
define([], function () {
var Test = {};
return Test;
});
Can someone help me solve this, please?
Many thanks
It seems Grunt doesn't load RequireJS. Maybe this could help you.

Configure a separate Grunt instance in a test

I have been writing a small grunt plugin, and now I am stuck trying to test the plugin end-to-end. What I would like to accomplish is this
Write a test case that configures a grunt instance with a minimal grunt config for my plugin and runs that task
Test that the file produced equals the intended output
Run that test automatically when running grunt nodeunit
So far, I seem stuck on configuring an individual Grunt instance, as the new instance seems to share configuration with that of the already loaded Grunt instance.
I got something like this in my plugin_test.js
var testGrunt = require('grunt');
exports.codekit = {
setUp: function(done) {
testGrunt.initConfig({
myPlugin : {
// the config
}
});
testGrunt.task.run(['myPlugin']);
done();
},
basic_parsing_works: function(test) {
test.expect(1); // no idea what this does
test.equal(1,1,'basic test');
//var actual = testGrunt.file.read('tmp/test01_result.html');
//var expected = testGrunt.file.read('expected/test01_expected.html');
//test.equal(actual, expected, 'should parse file.');
test.done();
}
};
The problem is that when I run the task for myPlugin it uses the configuration loaded in the "outer" (already running) Grunt instance. Even though I have specifically created a new Grunt instance under a different name (testGrunt).
Is there a way to avoid this?

grunt and qunit - running a single test

I already have grunt-contrib-qunit set up. My Gruntfile.js includes something like this
qunit: { files: ['test/*.html'] }
Now I can run grunt qunit and all my tests run.
Question: how can I run just one single test without running all of them? Is there a way I can overload the value of files from the command line?
You definitely need to look into grunt-contrib-qunit and grunt-contrib-connect (https://github.com/gruntjs/grunt-contrib-qunit and https://github.com/gruntjs/grunt-contrib-connect) as the tandem will provide you with a headless phantom and a local webserver.
UPDATE - as for running just one specific test, you could write something like this, listing your tests as separate targets for your qunit task:
grunt.initConfig({
qunit: {
justSomething: ['test/justsomething.html'],
justSomethingElse: ['test/justsomethingelse.html'],
all: ['test/*.html']
}
});
Then you can call grunt qunit:justSomething, or grunt qunit:all - this is not specific to qunit, though - see http://gruntjs.com/configuring-tasks
Now, if you would really like to use the target to specify a test name, you would go with something like:
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.initConfig({
qunit: {
all: ['test/**/*.html']
}
});
grunt.task.registerTask('foo', 'A sample task that run one test.', function(testname) {
if(!!testname)
grunt.config('qunit.all', ['test/' + testname + '.html']);
grunt.task.run('qunit:all');
});
}
Then call grunt foo:testname.
Yet again, this is not specific to qunit - but rather grunt task writing.
Hope that (finally) helps.

Categories

Resources