Angular tests failing with Failed to execute 'send' on 'XMLHttpRequest'

AngularUnit TestingKarma JasmineAngular Cli

Angular Problem Overview


I am trying to test my angular 4.1.0 component -

export class CellComponent implements OnInit {
  lines: Observable<Array<ILine>>;
  @Input() dep: string;
  @Input() embedded: boolean;
  @Input() dashboard: boolean;
  constructor(
    public dataService: CellService,
    private route: ActivatedRoute,
    private router: Router, private store: Store<AppStore>) {
  }
}

However, a simple "should create" test throws this cryptic error...

> NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'ng:///DynamicTestModule/module.ngfactory.js'.

so I found this question, which suggests that the issue is the component has @Input)_ params which aren't set, however, if I modify my test like so:

  it('should create', inject([CellComponent], (cmp: CellComponent) => {
    cmp.dep = '';
    cmp.embedded = false;
    cmp.dashboard = false;
    expect(cmp).toBeTruthy();
  }));

then I still get the same issue, similarly, if I remove the @Input() annotations from the component, still no difference. How can I get these tests to pass?

Angular Solutions


Solution 1 - Angular

This is a problem of the new Angular Cli. Run your test with --sourcemaps=false and you will get the right error messages.

See details here: https://github.com/angular/angular-cli/issues/7296

EDIT:

Shorthand for this is:

ng test -sm=false

As of angular 6 the command is:

ng test --source-map=false

Solution 2 - Angular

I had the same issue using angualar cli 6, I have used this tag to get the right error message :

ng test --source-map=false

Maybe it will help someone :) .

Solution 3 - Angular

For my case there was a mock data problem and in case of Array, I was returning string from the mock.

someApi = fixture.debugElement.injector.get(SomeApi);
spyOn(someApi, 'someMethod')
  .and.returnValue(Observable.of('this is not a string but array'));

> The error message is really distracting and was not telling the actual error. Running ng test --source=false pointed the correct error and line, and helped me to fix it quickly.

Many time it happens when you mock data is incomplete or incorrect.

Solution 4 - Angular

You can either set input() property to default value in component.ts

@Input() tableColumns: Array<any> = [];  
@Input() pageObj: any = '';

OR

Modify your component.spec.ts file in following way,

beforeEach(() => {  
   fixture = TestBed.createComponent(MyComponent);  
   component = fixture.componentInstance;  
   component.tableColumns = [];  
   component.pageObj = '';  
   fixture.detectChanges();  
});

Solution 5 - Angular

As suggested above here: https://stackoverflow.com/a/45570571/7085047 my problem was in my ngOnInit. I was calling a mock swagger-generated REST controller proxy. It was returning null, and I was subscribing to that null, which doesn't work...

The error came back:

Failed to load ng:///DynamicTestModule/MockNodeDashboardComponent_Host.ngfactory.js: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

I fixed the issue using ts-mockito: https://github.com/NagRock/ts-mockito

I added code to create a mock instance like this:

import { mock, instance, when } from 'ts-mockito';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';
import { MockScenario } from './vcmts-api-client/model/MockScenario';

const MockVcmtsnodemockresourceApi: VcmtsnodemockresourceApi = mock(VcmtsnodemockresourceApi);
const obs = Observable.create((observer: Observer<MockScenario[]>) => {
  observer.next(new Array<MockScenario>());
  observer.complete();
});
when(MockVcmtsnodemockresourceApi.getMockScenariosUsingGET()).thenReturn(obs);
const instanceMockVcmtsnodemockresourceApi: VcmtsnodemockresourceApi = instance(MockVcmtsnodemockresourceApi);

And then added the instance to the test's providers array like this:

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      ...
      providers: [
        ...
        { provide: VcmtsnodemockresourceApi, useValue: instanceMockVcmtsnodemockresourceApi },
        ...
      ]        
    }).compileComponents();
  }));

Solution 6 - Angular

This can be related to Chrome hiding an actual test error. The test area will be confusing some mock http factory that it can't load and therefore that is the error it will report. Most likely the error will be around the ngOnInit area where an object is, say, expecting sub objects and they are not defined.

To try and get to the bottom of the error, switch to PhantomJS temporarily which seems to suffer less from these initialisation errors and this will hopefully report the actual error to you. Several occasions I found to be where an object expected on initialisation wasn't complete. IE:

    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;

    component.object = {}
// should be:
    component.object = {"innerObjectThatIsNeeded" : []}

Correcting the object allowed PhantomJS to complete and also Chrome to move on to the next test.

Other than that I've not seen a solution to remove the issue from Chrome. As ever try and adopt a "remove the code, until error goes" policy to chase down the error.

UPDATE: Note this is now a quite an old answer, I wouldn't recommend using PhantomJS anymore (EOL). Browser test reporting has got a lot better and if Chrome is giving you grief then try Firefox, which also runs tests really well nowadays.

Solution 7 - Angular

I faced the same issue and I've found out that to fix it you have to set your inputs for the component in the method beforeEach as shown below:

beforeEach(() => {
	fixture = TestBed.createComponent(CellComponent );
	cmp = fixture.debugElement.componentInstance;
    cmp.dep = '';
    cmp.embedded = false;
    cmp.dashboard = false;
	fixture.detectChanges();
});

This will definitely resolve your issue.

Solution 8 - Angular

I also had this error, which truth be told is fairly non talkative.

It was related to the HTTP calls trough my services

I use myService.ts with 2 methods

get();
getAll();

I am mocking this service : mockMyService.ts

The error was here because my component was using getAll() method that I forgot to implement in the mockMyService, so I just added the method :

private mockObjects = [
{
  'id': '1',
  'champ1': 'TECH',
  'champ2': 2,
  'champ3': 'Data bidon'
},
{
  'id': '2',
  'champ1': 'TECH',
  'champ2': 2,
  'champ3': 'Data au pif'
},
{
  'id': '3',
  'champ1': 'FUNC',
  'champ2': 3,
  'champ3': 'Data quelconque'
},
 ];

getAll(): Observable<any> {
  return Observable.of(this.mockObjects);
}

Error was gone :)

Solution 9 - Angular

For me this message appear when a mock is falsy in my tests : usually you provide mockService in your tests bootstrap. If your mock is incomplete or falsy, then angular return this stupid error.

More information on my case [here][1]

[1]: https://stackoverflow.com/questions/45551214/angular-4-unit-test-error-failed-to-execute-send-on-xmlhttprequest-failed/45594338#45594338](https://stackoverflow.com/questions/45551214/angular-4-unit-test-error-failed-to-execute-send-on-xmlhttprequest-failed/45594338#45594338

Solution 10 - Angular

In my case the culprit was observable.timeout(x).retry(y) applied somewhere on the returned Observable on the service class level, then again in the component which was using that service.

Everything worked correctly in the browser up until angular-cli 1.4. Then started failing during Karma tests (with such a silly error). The solution was of course to tidy up these timeout/retry operators.

Solution 11 - Angular

What I would be doing is:

Add console.log() s, line after line in ngOnint() and find out how far it goes , then inspect the line which it wont pass through.

Ex:

ngOnInit() {
    this.route.paramMap
        .switchMap(params => {
            this.busy = true;
            this.updateErrors(null);

            console.log(params);

            **const id = params.get('id');**
            console.log(id);

            if (id === 'new') {
                this.editMode = true;
                return Observable.of(GroupComponent.newGroup());
            }
            return this.apiService.getGroup(id);
        })
    }

This was failing on my test with the same error in this post. As shown above, I had two console.logs. First one passed thorugh , but the second one not. So I realized the issue is on line const id = params.get('id'); and I fixed it.

Hope this will help someone.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGeorge EdwardsView Question on Stackoverflow
Solution 1 - AngularpenghuiView Answer on Stackoverflow
Solution 2 - AngularjmuhireView Answer on Stackoverflow
Solution 3 - AngularAniruddha DasView Answer on Stackoverflow
Solution 4 - AngularMangesh DaundkarView Answer on Stackoverflow
Solution 5 - AngularDatum GeekView Answer on Stackoverflow
Solution 6 - AngularPeterSView Answer on Stackoverflow
Solution 7 - AngularJayant PatilView Answer on Stackoverflow
Solution 8 - AngularDeunzView Answer on Stackoverflow
Solution 9 - AngularRebolonView Answer on Stackoverflow
Solution 10 - AngularMarcin RView Answer on Stackoverflow
Solution 11 - AngularJosfView Answer on Stackoverflow