简体   繁体   中英

Argument of type 'null' is not assignable to parameter of type 'HttpClient' on angular 11

I'm just learn to being developer, I have problem here when passing argument null as shown below:

todos.component.spec.ts

 import { TodosComponent } from './todos.component';
 import { TodoService } from './todo.service';
 import { Observable } from 'rxjs/Observable';
 import 'rxjs/add/observable/from';
    
    describe('TodosComponent', () => {
      let component: TodosComponent;
      let service: TodoService;
    
      beforeEach(() => {
        service = new TodoService(null); //Argument of type 'null' is not assignable to parameter of type 
      'HttpClient'.ts(2345)
        component = new TodosComponent(service);
      });
    
      it('6.1 Should set todos property with the items returned from the server', () => {
    
        const todos = [1, 2, 3];
        spyOn(service, 'getTodos').and.callFake(() => {
          return Observable.from([todos]);
        });
    
        component.ngOnInit();
    
        expect(component.todos).toBe(todos);
      });
    });

todo.component.ts

import { TodoService } from './todo.service'
    export class TodosComponent  { 
      todos: any;
      message: any; 
    
      constructor(private service: TodoService) {}
    
      ngOnInit() { 
        this.service.getTodos()
          .subscribe(t => this.todos = t);
      }
    
      add() { 
        var newTodo = { title: '... ' };
        this.service.add(newTodo)
          .subscribe(
          ( t => this.todos.push(t) ),
          ( err  => this.message = err) );
      }
    
      delete(id: number) {
        if (confirm('Are you sure?'))
          this.service.delete(id)
          .subscribe();
      }  
    }

todo.services.ts

import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/map';

    export class TodoService { 
      constructor(private http: HttpClient) { 
      }
    
      add(todo: { title: string; }) {
        return this.http.post('...', todo)
              .map((r => r.json()));
      }
    
      getTodos() { 
        return this.http.get('...')
              .map((r => r.json()));
      }
    
      delete(id: number) {
        return this.http.delete('...')
              .map((r => r.json()));
      }
    }

Here my environment used.

Angular CLI: 11.2.6
Node: 12.16.2
OS: win32 x64

Angular: 11.2.7
... animations, common, compiler, compiler-cli, core, elements
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1102.6
@angular-devkit/build-angular   0.1102.6
@angular-devkit/core            11.2.6
@angular-devkit/schematics      11.2.6
@angular/cdk                    11.2.6
@angular/cli                    11.2.6
@schematics/angular             11.2.6
@schematics/update              0.1102.6
ng-packagr                      11.2.4
rxjs                            6.6.6
typescript                      4.0.7

You need to inject HttpClient into your TodoService since it takes it as a parameter. Since we don't want to make physical http requests (since we are only testing the code and not the api), we will make a spy on the HttpClient , and pass it to the service.

import { of } from 'rxjs'

describe('TodosComponent', () => {
  beforeEach(() => {
    const spy = jasmine.createSpyObj('HttpClient', { post: of({}), get: of({}) })
    service = new TodoService(spy)
  })
})

Side Note:

You can simplify your your spy by doing the following:

let todos = [1,2,3,4]
spyOn(service, 'getTodos').and.returnValue(of(todos));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM