7

appComponent:

ngOninit(){
    this.http.get('../assets/data/dummy.json').subscribe(result => {
      this.favorites = result;
    });
}

test name: AppComponent should render title in a h1 tag

Karma message: Failed: Http failure response for http://localhost:9876/assets/data/dummy.json: 404 Not Found

If i put absolte path to json in the get method as http://localhost:4200/assets/data/dummy.json, the error is gone

2
  • 3
    Use the HttpClientTestingModule, so that you can mock the http backend in your unit tests. angular.io/guide/http#testing-http-requests Commented Jan 6, 2018 at 11:12
  • A unit test should mock http requests, you should not rely on a separate server running Commented Jan 6, 2018 at 11:41

1 Answer 1

7

The reason your test is failing is because the ngOnInit() in your component is making an actual http call to get that resource, dummy.json.

Good unit testing practices usually say that you should mock most portions of your application, except for the unit under test. This gives you more control, and allows your tests to explain better where the error is when you have a failure. When we use the actual http call to that resource, and the test fails, we do not know if it is because the resource wasn't retrieved or because the title was not rendered in an h1 tag. These two issues have nothing to do with each other, and should be in separate test cases. To do this, we mock the http call so we can ensure a successful response is received and then only focus on the title.

To do this, we can use the HttpClientTestingModule.

This is an example of app.component.ts to reflect your example above:

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  template: `
    <h1>{{ title }} app is running!</h1>
  `
})
export class AppComponent implements OnInit {
  favorites: {};
  title = 'Demo';

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.http.get('../assets/data/dummy.json').subscribe(result => {
      this.favorites = result;
    });
  }
}

And to make your AppComponent should render title in a h1 tag test pass, this is your spec file, app.component.spec.ts:

import { TestBed, async } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';

import { AppComponent } from './app.component';

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
      imports: [ HttpClientTestingModule ]
    }).compileComponents();
  }));

  it('AppComponent should render title in a h1 tag', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('h1').textContent).toContain('Demo app is running!');
  });
});

Notice, what we did to make this work is that we added HttpClientTestingModule to our list of imports in TestBed.configureTestingModule({}). We don't need to do anything else, when a component is created in this TestBed and asks for an HttpClient, the TestBed will provide it with the HttpClient from the HttpClientTestingModule. This will prevent all of your requests from actually being sent, and now your test will pass.

This worked for your case, but it also now lets you start performing tests on the http requests and responses. Check out https://angular.io/guide/http#testing-http-requests for much more info about HttpClientTestingModule and http testing in general.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.