赵玉全 發表於 2020-2-12 16:50:00

[Angular 8 Unit Testing] Angular 8 Unit Testing -- service

<h2>How to test a service</h2>
<p>The service we want to test against:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;collapse:true;;gutter:true;">import {Injectable} from '@angular/core';
import {LoggerService} from './logger.service';


@Injectable({
providedIn: 'root'
})
export class CalculatorService {


constructor(private logger: LoggerService) {

}

add(n1: number, n2:number) {
    this.logger.log("Addition operation called");
    return n1 + n2;
}

subtract(n1: number, n2:number) {
    this.logger.log("Subtraction operation called");
    return n1 - n2;
}


}
</pre>
</div>
<p> For this service, we want to test two things:</p>
<p><strong>1. add / subtract functions should return the correct values.</strong></p>
<p><strong>2. The logger service should be called only once for each method.</strong></p>
<p>&nbsp;</p>
<h4>Using Spy to mock a service</h4>
<p>For logger service, we don't want to call the real service, it might trigger side effects, for example, send analytics request. We want to mock a logger service:</p>
<div class="cnblogs_code">
<pre>    beforeEach(()=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      <strong><span style="color: rgba(255, 0, 255, 1); background-color: rgba(255, 255, 0, 1)">loggerSpy </span></strong></span><strong><span style="color: rgba(255, 0, 255, 1); background-color: rgba(255, 255, 0, 1)">= jasmine.createSpyObj('LoggerService', ['log'</span></strong><span style="color: rgba(0, 0, 0, 1)"><strong><span style="color: rgba(255, 0, 255, 1); background-color: rgba(255, 255, 0, 1)">])</span></strong>
      TestBed.configureTestingModule({
            providers: [
                CalculatorService,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> If you want to use spy, you have to use provide + useValue syntax, otherwise, Angular will init an actual
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> implementation of LoggerService.</span>
<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 255, 1)"><strong><span style="background-color: rgba(255, 255, 0, 1)">                {provide: LoggerService, useValue: loggerSpy}</span></strong></span>
            ]
      })
      calculator </span>= TestBed.<span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(CalculatorService)
    });</span></pre>
</div>
<p>&nbsp;</p>
<p>Full test code:</p>
<div class="cnblogs_code">
<pre>import {CalculatorService} <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./calculator.service</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
import {LoggerService} </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./logger.service</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
import {TestBed} </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@angular/core/testing</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> fdescribe</span>
describe(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">CalculatorService</span><span style="color: rgba(128, 0, 0, 1)">'</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {

    let calculator: CalculatorService,
      loggerSpy: any;

    beforeEach(()</span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      loggerSpy </span>= jasmine.createSpyObj(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">LoggerService</span><span style="color: rgba(128, 0, 0, 1)">'</span>, [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">log</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">])
      TestBed.configureTestingModule({
            providers: [
                CalculatorService,
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> If you want to use spy, you have to use provide + useValue syntax, otherwise, Angular will init an actual
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> implementation of LoggerService.</span>
<span style="color: rgba(0, 0, 0, 1)">                {provide: LoggerService, useValue: loggerSpy}
            ]
      })
      calculator </span>= TestBed.<span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(CalculatorService)
    });

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> fit</span>
    it(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">should add two numbers</span><span style="color: rgba(128, 0, 0, 1)">'</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">const</span> result = calculator.add(<span style="color: rgba(128, 0, 128, 1)">2</span>, <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
      expect(result).toBe(</span><span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">);
      expect(loggerSpy.log).toHaveBeenCalledTimes(</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">);
    });

    it(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">should subtract two numbers</span><span style="color: rgba(128, 0, 0, 1)">'</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {

      </span><span style="color: rgba(0, 0, 255, 1)">const</span> result = calculator.subtract(<span style="color: rgba(128, 0, 128, 1)">2</span>, <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">);
      expect(result).toBe(</span><span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">unexpected subtraction result</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
      expect(loggerSpy.log).toHaveBeenCalledTimes(</span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">);
    });
});</span></pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h4>Testing a service with HTTP request</h4>
<p>The service we want to test against:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;collapse:true;;gutter:true;">import { Injectable } from "@angular/core";
import { HttpClient, HttpParams } from "@angular/common/http";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
import { Lesson } from "../model/lesson";
import { Course } from "../model/course";

@Injectable()
export class CoursesService {
constructor(private http: HttpClient) {}

findCourseById(courseId: number): Observable&lt;Course&gt; {
    return this.http.get&lt;Course&gt;(`/api/courses/${courseId}`);
}

findAllCourses(): Observable&lt;Course[]&gt; {
    return this.http.get("/api/courses").pipe(map(res =&gt; res["payload"]));
}

saveCourse(courseId: number, changes: Partial&lt;Course&gt;): Observable&lt;Course&gt; {
    return this.http.put&lt;Course&gt;(`/api/courses/${courseId}`, changes);
}

findLessons(
    courseId: number,
    filter = "",
    sortOrder = "asc",
    pageNumber = 0,
    pageSize = 3
): Observable&lt;Lesson[]&gt; {
    return this.http
      .get("/api/lessons", {
      params: new HttpParams()
          .set("courseId", courseId.toString())
          .set("filter", filter)
          .set("sortOrder", sortOrder)
          .set("pageNumber", pageNumber.toString())
          .set("pageSize", pageSize.toString())
      })
      .pipe(map(res =&gt; res["payload"]));
}
}
</pre>
</div>
<p>  </p>
<p>For this service, we also don't want to issue a real http request, therefore we also need to mock a HTTP service, Angular provides <strong>HttpClientTestingModule</strong> for us. We can use the <span style="background-color: rgba(255, 255, 0, 1); color: rgba(255, 0, 255, 1)"><strong>HttpTestingController</strong></span>.</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">let coursesService: CoursesService,
    httpTestingController: HttpTestingController;

beforeEach(() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    TestBed.configureTestingModule({
      imports: [<span style="background-color: rgba(255, 255, 0, 1); color: rgba(255, 0, 255, 1)"><strong>HttpClientTestingModule</strong></span>],
      providers:
    });

    (coursesService </span>= TestBed.<span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(CoursesService)),
      (<span style="color: rgba(255, 0, 255, 1); background-color: rgba(255, 255, 0, 1)"><strong>httpTestingController </strong></span></span><span style="color: rgba(255, 0, 255, 1); background-color: rgba(255, 255, 0, 1)"><strong>= TestBed.get</strong></span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 255, 1); background-color: rgba(255, 255, 0, 1)"><strong>(HttpTestingController)</strong></span>);
});</span></pre>
</div>
<p>&nbsp;</p>
<p>Example code:</p>
<div class="cnblogs_code">
<pre>it(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">should retrieve all courses</span><span style="color: rgba(128, 0, 0, 1)">"</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    coursesService.findAllCourses().subscribe(courses </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      expect(courses).toBeTruthy(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">No courses returned</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

      expect(courses.length).toBe(</span><span style="color: rgba(128, 0, 128, 1)">12</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">incorrect number of courses</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

      </span><span style="color: rgba(0, 0, 255, 1)">const</span> course = courses.find(course =&gt; course.id == <span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">);

      expect(course.titles.description).toBe(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Angular Testing Course</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    });
    <span style="color: rgba(51, 153, 102, 1)">// expect only one request
    </span></span><span style="color: rgba(0, 0, 255, 1)">const</span> req = httpTestingController.expectOne(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/api/courses</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    <span style="color: rgba(51, 153, 102, 1)">// check the request should be the GET request</span>
    expect(req.request.method).toEqual(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">GET</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    <span style="color: rgba(51, 153, 102, 1)">// issue the mock http request and return the response</span>
    req.flush({ payload: Object.values(COURSES) });
});</span></pre>
</div>
<p>&nbsp;</p>
<h4>Testing a error HTTP request</h4>
<p>Calling 'fail' method from Jasmine in the success block, which means "This test should in Error block, but landed on Success block, so we consider the test is failed."</p>
<div class="cnblogs_code">
<pre>it(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">should give an error if save course fails</span><span style="color: rgba(128, 0, 0, 1)">"</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">const</span> changes: Partial&lt;Course&gt; =<span style="color: rgba(0, 0, 0, 1)"> {
      titles: { description: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Testing Course</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
    };
    coursesService.saveCourse(</span><span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">, changes).subscribe(
      () </span>=&gt; <span style="color: rgba(255, 0, 255, 1)"><strong><span style="background-color: rgba(255, 255, 0, 1)">fail</span></strong></span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">save course operation should have failed</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">),
      (error: HttpErrorResponse) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      <span style="background-color: rgba(255, 255, 0, 1); color: rgba(255, 0, 255, 1)"><strong>expect(error.status).toBe(</strong></span></span><span style="background-color: rgba(255, 255, 0, 1); color: rgba(255, 0, 255, 1)"><strong>500</strong></span><span style="color: rgba(0, 0, 0, 1)"><span style="background-color: rgba(255, 255, 0, 1); color: rgba(255, 0, 255, 1)"><strong>);</strong></span>
      }
    );

    </span><span style="color: rgba(0, 0, 255, 1)">const</span> req = httpTestingController.expectOne(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/api/courses/12</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.body.titles.description).toEqual(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Testing Course</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.method).toBe(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PUT</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    req.flush(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">save course fail</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, <span style="background-color: rgba(255, 255, 0, 1); color: rgba(255, 0, 255, 1)"><strong>{
      status: </strong></span></span><span style="background-color: rgba(255, 255, 0, 1); color: rgba(255, 0, 255, 1)"><strong>500,
      statusText: "Internal server error"</strong></span><span style="color: rgba(0, 0, 0, 1)"><span style="background-color: rgba(255, 255, 0, 1); color: rgba(255, 0, 255, 1)"><strong>
    }</strong></span>);
});</span></pre>
</div>
<p>&nbsp;</p>
<h4>Testing HTTP params</h4>
<p>Example Code:</p>
<div class="cnblogs_code">
<pre>it(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">should find a list of lessons</span><span style="color: rgba(128, 0, 0, 1)">"</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    coursesService.findLessons(</span><span style="color: rgba(128, 0, 128, 1)">12</span>).subscribe(lessons =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      expect(lessons).toBeTruthy();
      expect(lessons.length).toBe(</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">);
    });
    <span style="color: rgba(51, 153, 102, 1)">// expectOne can also take function
    </span></span><span style="color: rgba(0, 0, 255, 1)">const</span> req =<span style="color: rgba(0, 0, 0, 1)"> httpTestingController.expectOne(
      req </span>=&gt; req.url == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/api/lessons</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    );
    expect(req.request.method).toEqual(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">GET</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">courseId</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">12</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">filter</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">sortOrder</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">asc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">pageNumber</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">pageSize</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">3</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

    req.flush({
      payload: findLessonsForCourse(</span><span style="color: rgba(128, 0, 128, 1)">12</span>).slice(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">)
    });
});</span></pre>
</div>
<p>&nbsp;</p>
<p>--</p>
<p>Full testing code:</p>
<div class="cnblogs_code">
<pre>import { CoursesService } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">./courses.service</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
import { TestBed } </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">@angular/core/testing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
import {
HttpClientTestingModule,
HttpTestingController
} </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">@angular/common/http/testing</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
import { COURSES, findLessonsForCourse } </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">../../../../server/db-data</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
import { Course } </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">../model/course</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
import { HttpErrorResponse } </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">@angular/common/http</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;

fdescribe(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CoursesService</span><span style="color: rgba(128, 0, 0, 1)">"</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
let coursesService: CoursesService,
    httpTestingController: HttpTestingController;

beforeEach(() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    TestBed.configureTestingModule({
      imports: ,
      providers:
    });

    (coursesService </span>= TestBed.<span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(CoursesService)),
      (httpTestingController </span>= TestBed.<span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(HttpTestingController));
});

it(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">should retrieve all courses</span><span style="color: rgba(128, 0, 0, 1)">"</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    coursesService.findAllCourses().subscribe(courses </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      expect(courses).toBeTruthy(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">No courses returned</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

      expect(courses.length).toBe(</span><span style="color: rgba(128, 0, 128, 1)">12</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">incorrect number of courses</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

      </span><span style="color: rgba(0, 0, 255, 1)">const</span> course = courses.find(course =&gt; course.id == <span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">);

      expect(course.titles.description).toBe(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Angular Testing Course</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    });

    </span><span style="color: rgba(0, 0, 255, 1)">const</span> req = httpTestingController.expectOne(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/api/courses</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

    expect(req.request.method).toEqual(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">GET</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

    req.flush({ payload: Object.values(COURSES) });
});

it(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">should save the course data</span><span style="color: rgba(128, 0, 0, 1)">"</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">const</span> changes: Partial&lt;Course&gt; =<span style="color: rgba(0, 0, 0, 1)"> {
      titles: { description: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Testing Course</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
    };

    coursesService.saveCourse(</span><span style="color: rgba(128, 0, 128, 1)">12</span>, changes).subscribe(course =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      expect(course.id).toEqual(</span><span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">);
    });

    </span><span style="color: rgba(0, 0, 255, 1)">const</span> req = httpTestingController.expectOne(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/api/courses/12</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.body.titles.description).toEqual(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Testing Course</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.method).toBe(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PUT</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    req.flush({
      ...COURSES[</span><span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">],
      ...changes
    });
});

it(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">should give an error if save course fails</span><span style="color: rgba(128, 0, 0, 1)">"</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 0, 255, 1)">const</span> changes: Partial&lt;Course&gt; =<span style="color: rgba(0, 0, 0, 1)"> {
      titles: { description: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Testing Course</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> }
    };
    coursesService.saveCourse(</span><span style="color: rgba(128, 0, 128, 1)">12</span><span style="color: rgba(0, 0, 0, 1)">, changes).subscribe(
      () </span>=&gt; fail(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">save course operation should have failed</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">),
      (error: HttpErrorResponse) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      expect(error.status).toBe(</span><span style="color: rgba(128, 0, 128, 1)">500</span><span style="color: rgba(0, 0, 0, 1)">);
      }
    );

    </span><span style="color: rgba(0, 0, 255, 1)">const</span> req = httpTestingController.expectOne(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/api/courses/12</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.body.titles.description).toEqual(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Testing Course</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.method).toBe(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PUT</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    req.flush(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">save course fail</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, {
      status: </span><span style="color: rgba(128, 0, 128, 1)">500</span><span style="color: rgba(0, 0, 0, 1)">,
      statusText: </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Internal server error</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    });
});

it(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">should find a list of lessons</span><span style="color: rgba(128, 0, 0, 1)">"</span>, () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    coursesService.findLessons(</span><span style="color: rgba(128, 0, 128, 1)">12</span>).subscribe(lessons =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      expect(lessons).toBeTruthy();
      expect(lessons.length).toBe(</span><span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">);
    });

    </span><span style="color: rgba(0, 0, 255, 1)">const</span> req =<span style="color: rgba(0, 0, 0, 1)"> httpTestingController.expectOne(
      req </span>=&gt; req.url == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/api/lessons</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
    );
    expect(req.request.method).toEqual(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">GET</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">courseId</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">12</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">filter</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">sortOrder</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">asc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">pageNumber</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
    expect(req.request.</span><span style="color: rgba(0, 0, 255, 1)">params</span>.<span style="color: rgba(0, 0, 255, 1)">get</span>(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">pageSize</span><span style="color: rgba(128, 0, 0, 1)">"</span>)).toEqual(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">3</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);

    req.flush({
      payload: findLessonsForCourse(</span><span style="color: rgba(128, 0, 128, 1)">12</span>).slice(<span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">)
    });
});

afterEach(() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> make sure the no extra http request are called</span>
<span style="color: rgba(0, 0, 0, 1)">    httpTestingController.verify();
});
});</span></pre>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/Answer1215/p/12299646.html
頁: [1]
查看完整版本: [Angular 8 Unit Testing] Angular 8 Unit Testing -- service