Unit Test Failed: Cannot read property 'componentInstance' of undefined - unit-testing

Unit test works fine with angular2-seed project. The problem is it does not work with my project which resembles angular2-seed project.
Only difference between my project and angular2-seed is that I use gulpfile.ts without using tools directory. I defined all gulp tasks in a single file.
I need some help to give me some hint on this error.
I have this very simplified component
import {Component} from 'angular2/core';
import {RouterLink, Router} from 'angular2/router';
import {CORE_DIRECTIVES} from 'angular2/common';
#Component({
selector: 'cet-login',
moduleId: module.id,
templateUrl: 'apps/common/features/login/login.tpl.html',
directives: [RouterLink, CORE_DIRECTIVES]
})
export class LoginComponent {
constructor(
private router: Router
) {}
}
and I have very simple unit test
import {
TestComponentBuilder,
describe,
expect,
injectAsync,
it
} from 'angular2/testing';
import {Component} from 'angular2/core';
import {LoginComponent} from './login.cmp';
export function main(): void {
'use strict';
describe('Login component', () => {
it('should work',
injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb.createAsync(TestComponent)
.then(rootTC => {
rootTC.detectChanges();
expect(1).toBe(1);
});
}));
});
}
class Mock {}
#Component({
selector: 'test-cmp',
template: '<cet-login></cet-login>',
directives: [LoginComponent]
})
class TestComponent {}
I also have gulpfile.ts test section like the following;
gulp.task('test:buildjs', 'Compile typescript test files', ['test:buildcss'], () => {
var tsProject = tsProjectFn();
var result = gulp.src(PATH.src.ts)
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(inlineNg2Template({base: PATH.src.base}))
.pipe(tsc(tsProject));
return result.js
.pipe(sourcemaps.init())
.pipe(gulp.dest(PATH.dest.test));
});
gulp.task('test:unit', 'Start a karma server and run a unit test', (done: any) => {
return new karma.Server({
configFile: __dirname + '/karma.config.js',
singleRun: true
}).start(done);
});
When I run gulp test, which runs test:buildjs and test:unit, I have the following error
1) should work
Login component
Failed: Cannot read property 'componentInstance' of undefined
TypeError: Cannot read property 'componentInstance' of undefined
at new ComponentFixture_ (C:/repos/FAR/node_modules/angular2/src/testing/test_component_builder.js:38:51)
at C:/repos/FAR/node_modules/angular2/src/testing/test_component_builder.js:204:52
at Zone.run (C:/repos/FAR/node_modules/zone.js/dist/zone-microtask.js:1217:24)
at zoneBoundFn (C:/repos/FAR/node_modules/zone.js/dist/zone-microtask.js:1194:26)
at lib$es6$promise$$internal$$tryCatch (C:/repos/FAR/node_modules/zone.js/dist/zone-microtask.js:442:17)
at lib$es6$promise$$internal$$invokeCallback (C:/repos/FAR/node_modules/zone.js/dist/zone-microtask.js:454:18)
at lib$es6$promise$$internal$$publish (C:/repos/FAR/node_modules/zone.js/dist/zone-microtask.js:425:12)
at C:/repos/FAR/node_modules/zone.js/dist/zone-microtask.js:97:10
at Zone.run (C:/repos/FAR/node_modules/zone.js/dist/zone-microtask.js:1217:24)
at zoneBoundFn (C:/repos/FAR/node_modules/zone.js/dist/zone-microtask.js:1194:26)
at lib$es6$promise$asap$$flush (C:/repos/FAR/node_modules/zone.js/dist/zone-microtask.js:236:10)
karma.config.js is exactly the same as angualr2-seed
test-main.js is the exactly the same as angualr2-seed
Any idea what I miss and what I am doing wrong?

I don't know which version of Angular2 (in my case beta7+) you use but in my unit tests, I need to register TEST_BROWSER_PLATFORM_PROVIDERS and TEST_BROWSER_APPLICATION_PROVIDERS to be able to use the TestComponentBuilder class:
import {
it,
describe,
expect,
beforeEach,
inject,
injectAsync,
TestComponentBuilder,
ComponentFixture,
setBaseTestProviders
} from 'angular2/testing';
import {
TEST_BROWSER_PLATFORM_PROVIDERS,
TEST_BROWSER_APPLICATION_PROVIDERS
} from 'angular2/platform/testing/browser';
import {MyListComponent} from "./my-list";
import {MyService} from "../services/my-service";
describe('MyList Tests', () => {
setBaseTestProviders(TEST_BROWSER_PLATFORM_PROVIDERS,
TEST_BROWSER_APPLICATION_PROVIDERS);
let list:MyListComponent;
beforeEach(() => {
list = new MyListComponent();
});
it('should render list', injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb.createAsync(MyListComponent).then((componentFixture: ComponentFixture) => {
const element = componentFixture.nativeElement;
componentFixture.detectChanges();
expect(element.querySelectorAll('li').length).toBe(3);
});
}));
});
See this plunkr: https://plnkr.co/edit/oVBPsH?p=preview.

Found the cause of this problem. The following line should be commented out for successful test.
import {enableProdMode} from 'angular2/core';
enableProdMode();

Related

Why is FormControl not marked dirty in Angular 10 unit test?

The following test passes with Angular 9, but fails with Angular 10. Why?
upgrade-test.component.html:
<input [formControl]="formControl" />
upgrade-test.component.ts
import { Component } from '#angular/core';
import { FormControl } from '#angular/forms';
#Component({
selector: 'app-upgrade-test',
templateUrl: './upgrade-test.component.html'
})
export class UpgradeTestComponent {
formControl: FormControl = new FormControl(0);
}
upgrade-test.component.spec.ts:
import { TestBed } from '#angular/core/testing';
import { UpgradeTestComponent } from './upgrade-test.component';
import { ReactiveFormsModule } from '#angular/forms';
describe('Test', () => {
TestBed.configureTestingModule({
declarations: [UpgradeTestComponent],
imports: [ReactiveFormsModule],
});
it('should pass', () => {
const fixture = TestBed.createComponent(UpgradeTestComponent);
const component = fixture.componentInstance;
fixture.detectChanges();
expect(component.formControl.dirty).toBeFalsy();
component.formControl.patchValue(1);
const inputElem: HTMLInputElement = fixture.nativeElement.querySelector('input');
inputElem.dispatchEvent(new Event('change'));
fixture.detectChanges();
expect(component.formControl.dirty).toBeTruthy();
});
});
Test result:
Test
✗ should pass
Expected false to be truthy.
at UserContext. (http://localhost:9876/_karma_webpack_/src/app/components/upgrade-test/upgrade-test.component.spec.ts:21:41)
at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:364:1)
at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:292:1)
at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:363:1)
Because the patchValue() or setValue() methods do not change the dirty status of the control or the form.
A control is dirty if the user has changed the value in the UI.
https://angular.io/api/forms/AbstractControl#dirty

Setting up a Test Bed in Ionic Provider

I am really new into Ionic and Unit Testing. Current version is 3.12.0. I am using Karma and Jasmine for unit testing.
I have a provider called test-service.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
/*
Generated class for the TestServiceProvider provider.
See https://angular.io/guide/dependency-injection for more info on providers
and Angular DI.
*/
#Injectable()
export class TestServiceProvider {
constructor(public http: Http) {
console.log('Hello TestServiceProvider Provider');
}
}
Then I have a test spec in the same folder as follows contains a simple test with a test bed.
import { TestServiceProvider } from './test-service';
import { TestBed, TestModuleMetadata, async, ComponentFixture } from '#angular/core/testing';
describe('Test Service', () => {
let component: TestServiceProvider;
let fixture: ComponentFixture<TestServiceProvider>;
beforeEach(async( () => {
TestBed.configureTestingModule({
imports: [TestServiceProvider]
}).compileComponents;
}));
beforeEach( () => {
fixture = TestBed.createComponent(TestServiceProvider);
component = fixture.componentInstance;
});
it('should add numbers', () => {
expect(1+1).toBe(2);
});
});
But when I run npm test it gives me an error
Unexpected value 'TestServiceProvider' imported by the module 'DynamicTestModule'. Please add a #NgModule annotation.
What am I doing wrong here and how do I fix this?
TestServiceProvider must be in the declaration not in Imports
Change Your code as below :
beforeEach(async( () => {
TestBed.configureTestingModule({
declarations: [TestServiceProvider]
}).compileComponents;
}));

Redux: How to test a connected component?

I am using Enzyme to unit test my React components. I understand that in order to test the raw unconnected component I'd have to just export it and test it (I've done that). I have managed to write a test for the connected component but I am really not sure if this's the right way and also what exactly would I want to test for the connected component.
Container.jsx
import {connect} from 'react-redux';
import Login from './Login.jsx';
import * as loginActions from './login.actions';
const mapStateToProps = state => ({
auth: state.auth
});
const mapDispatchToProps = dispatch => ({
loginUser: credentials => dispatch(loginActions.loginUser(credentials))
});
export default connect(mapStateToProps, mapDispatchToProps)(Login);
Container.test.js
import React from 'react';
import {Provider} from 'react-redux';
import {mount, shallow} from 'enzyme';
import {expect} from 'chai';
import LoginContainer from '../../src/login/login.container';
import Login from '../../src/login/Login';
describe('Container Login', () => {
it('should render the container component', () => {
const storeFake = state => ({
default: () => {
},
subscribe: () => {
},
dispatch: () => {
},
getState: () => ({ ...state })
});
const store = storeFake({
auth: {
sport: 'BASKETBALL'
}
});
const wrapper = mount(
<Provider store={store}>
<LoginContainer />
</Provider>
);
expect(wrapper.find(LoginContainer).length).to.equal(1);
const container = wrapper.find(LoginContainer);
expect(container.find(Login).length).to.equal(1);
expect(container.find(Login).props().auth).to.eql({ sport: 'BASKETBALL' });
});
});
This is an interesting question.
I usually do import both container and component to do the testing. For container testing I use, redux-mock-store. Component testing is for testing async functions. For instance in your case, login process is an async function using sinon stubs. Here is a snippet of the same,
import React from 'react';
import {Provider} from 'react-redux';
import {mount, shallow} from 'enzyme';
import {expect} from 'chai';
import LoginContainer from '../../src/login/login.container';
import Login from '../../src/login/Login';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { stub } from 'sinon';
const mockStore = configureMockStore([thunk]);
describe('Container Login', () => {
let store;
beforeEach(() => {
store = mockStore({
auth: {
sport: 'BASKETBALL',
},
});
});
it('should render the container component', () => {
const wrapper = mount(
<Provider store={store}>
<LoginContainer />
</Provider>
);
expect(wrapper.find(LoginContainer).length).to.equal(1);
const container = wrapper.find(LoginContainer);
expect(container.find(Login).length).to.equal(1);
expect(container.find(Login).props().auth).to.eql({ sport: 'BASKETBALL' });
});
it('should perform login', () => {
const loginStub = stub().withArgs({
username: 'abcd',
password: '1234',
});
const wrapper = mount(<Login
loginUser={loginStub}
/>);
wrapper.find('button').simulate('click');
expect(loginStub.callCount).to.equal(1);
});
});
As you pointed out, the way I usually do this is to export the un-connected component as well, and test that.
i.e.
export {Login};
Here's an example. Source of the component, and source of the tests.
For the wrapped component, I don't author tests for those because my mappings (mapStateToProps and mapDispatchToProps) are generally very simple. If I wanted to test a wrapped component, I'd really just be testing those maps. So those are what I would choose to explicitly test, rather than re-testing the entire component in a wrapped form.
There are two ways to test those functions. One way would be to export the functions within the module itself.
i.e.;
export {mapStateToProps, mapDispatchToProps}
I'm not a huge fan of this, because I wouldn't want other modules in the app to access them. In my tests, I sometimes use babel-plugin-rewire to access "in-scope" variables, so that's what I would do in this situation.
That might look something like:
import {
Login, __Rewire__
}
const mapStateToProps = __Rewire__.__get__('mapStateToProps');
describe('mapStateToProps', () => { ... });
If we have a router issue, we can consider to add the router lib into the test file, eg:
import React from 'react';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
import { mount } from 'enzyme';
import ReadDots from './ReadDots';
const storeFake = state => ({
default: () => {
},
subscribe: () => {
},
dispatch: () => {
},
getState: () => ({ ...state })
});
const store = storeFake({
dot: {
dots: [
{
id: '1',
dot: 'test data',
cost: '100',
tag: 'pocket money'
}
]
}
});
describe('<ReadDots />', () => {
it('should render ReadDots component', () => {
const component = mount(
<Provider store={store}>
<Router>
<ReadDots />
</Router>
</Provider>
);
expect(component.length).toEqual(1);
});
});

Error when setting base test providers into several unit tests

I use Angular2 RC1 and I have several unit tests regarding different components with the following structure:
import {provide} from '#angular/core';
import {
TestComponentBuilder
} from '#angular/compiler/testing';
import {
beforeEach,
ddescribe,
xdescribe,
describe,
expect,
iit,
inject,
injectAsync,
async,
beforeEachProviders,
setBaseTestProviders,
it,
xit
} from '#angular/core/testing';
import {
TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS
} from '#angular/platform-browser-dynamic/testing/browser';
describe('Test component 1', () => {
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
it('should something',
async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
var updateService = new UpdateService();
tcb.overrideProviders(ShapeCircleLayerComponent, [
provide(UpdateService, { useValue: updateService })
])
.createAsync(Component1).then((componentFixture) => {
(...)
});
});
});
});
Each test works if run alone but when I run them at the same time within Karma, I get the following error:
Chrome 50.0.2661 (Linux 0.0.0) Test for shape circle layer encountered a declaration exception FAILED
Error: Cannot set /home/(...)/my-project providers because it has already been called
at new BaseException (/home/(...)/my-project/node_modules/#angular/core/src/facade/exceptions.js:17:23)
at Object.setBaseTestProviders (/home/(...)/my-project/node_modules/#angular/core/testing/test_injector.js:74:15)
```
It seems that several tests that set base test providers (TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS) can't be executed at the same time.
Does anyone have this problem? Thanks very much!
As #teleaziz suggested, you should do this only once. So such processing needs to be moved into the karma-test-shim.js file. Here is a sample:
System.import('#angular/platform-browser/src/browser/browser_adapter')
.then(function(browser_adapter) { browser_adapter.BrowserDomAdapter.makeCurrent(); })
.then(function() {
return Promise.all([
System.import('#angular/core/testing'),
System.import('#angular/platform-browser-dynamic/testing/browser')
]);
})
.then(function(modules) {
var testing = modules[0];
var testingBrowser = modules[1];
testing.setBaseTestProviders(
testingBrowser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
testingBrowser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
})
.then(function() { return Promise.all(resolveTestFiles()); })
.then(function() { __karma__.start(); }, function(error) { __karma__.error(error.stack || error); });

Trouble unit testing service with the Router injected in the constructor in Angular 2

I'm trying to test a service that has the application router injected in its constructor. Following Julie Ralph's suggestions presented in AngularConnect conf 2015 (and her repository: https://github.com/juliemr/ng2-test-seed),
I'm using Karma and Jasmine.
It follows the example service to be tested:
import { Router } from 'angular2/router';
export class ExampleService {
constructor(router : Router) {
this._router = router;
}
//...
}
Right now, I'm just asserting the truth. It follows the service test:
import { it, describe, expect, inject, beforeEachProviders, MockApplicationRef } from 'angular2/testing';
import { ROUTER_PROVIDERS } from 'angular2/router';
import { provide, ApplicationRef } from 'angular2/core';
import { ExampleService } from 'example-service.js';
describe('ExampleService', () => {
beforeEachProviders(() => [
ROUTER_PROVIDERS, ExampleService,
provide(ApplicationRef, { useClass: MockApplicationRef })
]);
it('should validate the truth', inject([ExampleService], (exService) => {
expect(true).toBeTruthy();
}));
});
when I run the tests ( > karma start karma.config.js ), I get a TypeError: Cannot read property 'length' of null
Looking at the router.js source code, it looks like I should bootstrap at least one component before injecting router. Is there
an easy way to inject the Router dependency in a test?
The Stacktrace:
ORIGINAL EXCEPTION: TypeError: Cannot read property 'length' of null
ORIGINAL STACKTRACE:
TypeError: Cannot read property 'length' of null
at routerPrimaryComponentFactory (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/router.js:2963:27)
at Injector._instantiate (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11920:19)
at Injector._instantiateProvider (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21)
at Injector._new (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19)
at InjectorDynamicStrategy.getObjByKeyId (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42)
at Injector._getByKeyDefault (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33)
at Injector._getByKey (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21)
at Injector._getByDependency (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11990:21)
at Injector._instantiate (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11887:32)
at Injector._instantiateProvider (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21)
at Injector._new (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19)
at InjectorDynamicStrategy.getObjByKeyId (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42)
at Injector._getByKeyDefault (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33)
at Injector._getByKey (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21)
at Injector._getByDependency (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11990:21)
at Injector._instantiate (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11887:32)
at Injector._instantiateProvider (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21)
at Injector._new (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19)
at InjectorDynamicStrategy.getObjByKeyId (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42)
at Injector._getByKeyDefault (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33)
at Injector._getByKey (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21)
at Injector._getByDependency (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11990:21)
at Injector._instantiate (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11887:32)
at Injector._instantiateProvider (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21)
at Injector._new (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19)
at InjectorDynamicStrategy.getObjByKeyId (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42)
at Injector._getByKeyDefault (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33)
at Injector._getByKey (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21)
at Injector.get (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11804:19)
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2477:25
at Array.map (native)
at Array.map (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/es6-shim/es6-shim.js:1113:14)
at FunctionWithParamTokens.execute (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2476:33)
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2601:25
at Zone.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2-polyfills.js:138:17)
at Zone.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2544:30)
at runInTestZone (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2588:23)
at Object. (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2600:33)
at attemptAsync (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1819:24)
at QueueRunner.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1774:9)
at QueueRunner.execute (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1762:10)
at Spec.Env.queueRunnerFactory (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:627:35)
at Spec.execute (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:353:10)
at Object.fn (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2360:37)
at attemptAsync (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1819:24)
at QueueRunner.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1774:9)
at QueueRunner.execute (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1762:10)
at Env.queueRunnerFactory (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:627:35)
at Object.fn (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2345:13)
at attemptAsync (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1819:24)
at QueueRunner.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1774:9)
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1801:16
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1745:9
at queueRunnerFactory.onComplete (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2348:17)
at QueueRunner.clearStack (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:605:9)
at QueueRunner.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1784:12)
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1801:16
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1745:9
at complete (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:365:9)
See also https://github.com/angular/angular/issues/6325
Problem solved, just need to provide the ROUTER_PRIMARY_COMPONENT.
import {ROUTER_PRIMARY_COMPONENT} from 'angular2/router';
class MockPrimaryComponent {
}
beforeEachProviders(() => [
ROUTER_PROVIDERS,
provide(ROUTER_PRIMARY_COMPONENT, {useClass: MockPrimaryComponent}),
ExampleService,
provide(ApplicationRef, { useClass: MockApplicationRef })
]);
I know this post is related to the old router, but I thought it might be useful to answer this. Using angular version rc.1 with the new router, I got unit tests with the router, including testing navigateByUrl, by using this test within angular as inspiration: https://github.com/angular/angular/blob/master/modules/%40angular/router/test/integration_spec.ts
saved me a lot of hastle
Here's a working example
import {setBaseTestProviders,beforeEachProviders,inject,it,describe,expect,beforeEach} from '#angular/core/testing'
import { Component,provide} from '#angular/core';
import {Routes,ROUTER_DIRECTIVES,Route} from "#angular/router";
import {ComponentResolver} from '#angular/core';
import {Router,RouterOutletMap,RouteSegment,RouterUrlSerializer,DefaultRouterUrlSerializer} from '#angular/router';
import {SpyLocation} from '#angular/common/testing';
import {Location} from '#angular/common';
import {ComponentFixture, TestComponentBuilder} from '#angular/compiler/testing';
import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from '#angular/platform-browser-dynamic/testing';
#Component({
selector: 'some-component',
template: `Blah!`,
directives: [ROUTER_DIRECTIVES]
})
export class SomeComponent {
}
#Component({
selector: 'another-component',
template: `Blah!`,
directives: [ROUTER_DIRECTIVES]
})
export class AnotherComponent {
}
#Component({
selector: 'root-cmp',
template: `<router-outlet></router-outlet>`,
directives: [ROUTER_DIRECTIVES]
})
#Routes([
new Route({path: '/some-path',component:SomeComponent}),
new Route({path: '/another-path',component:AnotherComponent})
])
export class RootCmp {
}
export const PROVIDERS_TESTING = [
provide(RouterUrlSerializer, {useClass: DefaultRouterUrlSerializer}),
RouterOutletMap,
provide(Location, {useClass: SpyLocation}),
provide(RouteSegment, {useFactory: (r) => r.routeTree.root, deps: [Router]}),
provide(Router,{
useFactory: (resolver, urlParser, outletMap, location) => new Router(
"RootComponent", RootCmp, resolver, urlParser, outletMap, location),
deps: [ComponentResolver, RouterUrlSerializer, RouterOutletMap, Location]
}
),
]
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,[TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS,PROVIDERS_TESTING]);
it('some test',inject([Router, TestComponentBuilder, Location], (router:Router, tcb:TestComponentBuilder, location:Location) => {
return new Promise((resolve,reject)=>{
tcb.createAsync(RootCmp).then(fixture=>{
router.navigateByUrl('/some-path').then(()=>{
expect(location.path()).toEqual('/some-path');
resolve()
})
})
})
}))
it('another test',inject([Router, TestComponentBuilder, Location], (router:Router, tcb:TestComponentBuilder, location:Location) => {
return new Promise((resolve,reject)=>{
tcb.createAsync(RootCmp).then(fixture=>{
router.navigateByUrl('/another-path').then(()=>{
expect(location.path()).toEqual('/another-path');
resolve()
})
})
})
}))