在最后的小节中,我们解决一下两个小问题: ## 错误的单元测试 当我们修正所有的`fdescribe`及`fit`为`describe`及`it`,再运行`ng test`将启用对项目的全局测试。一个用于生产的项目,是应该保证每次进行功能新增及功能变更时单元测试全部通过的。为了在以后我们的开发中也能达到此效果,我们修正下前期未做整理的单元测试。使用`ng test`来进行全局测试: ### 错误一 ``` AppComponent > should have as title 'web-app' Expected undefined to equal 'web-app'. Error: Expected undefined to equal 'web-app'. at <Jasmine> at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/src/app/app.component.spec.ts:26:23) ``` 修正app.component.spec.ts ``` import { TestBed, async } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule ], declarations: [ AppComponent ], }).compileComponents(); })); it('should create the app', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.debugElement.componentInstance; expect(app).toBeTruthy(); }); }); ``` ### 错误二 ``` IndexComponent > 测试V层的交互操作 Failed: Template parse errors: Can't bind to 'routerLink' since it isn't a known property of 'a'. (" <td>{{klass.name}}</td> <td>{{klass.teacher.name}}</td> <td><a [ERROR ->]routerLink="./edit/{{klass.id}}">编辑</a></td> </tr> </table> "): ng:///DynamicTestModule/IndexComponent.html@16:11 ``` 修正klass/index/index.component.ts ``` beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [IndexComponent], imports: [HttpClientTestingModule, FormsModule, RouterTestingModule] }) .compileComponents(); })); ``` ### 错误三 ![](https://img.kancloud.cn/a5/74/a5741d88aa626d9af81c35533ab17ec3_528x171.png) 这是由于我们在选择教师组件中的如下代码,没有进行前置判断。 klass/teacher-select.component.ts ``` /** * 获取所有的教师,并传给V层 */ ngOnInit() { this.teacherSelect = new FormControl(); const url = 'http://localhost:8080/Teacher'; this.httpClient.get(url) .subscribe((teachers: Array<Teacher>) => { this.teachers = teachers; this.teachers.forEach((teacher: Teacher) => { if (this.teacher) { ✚ if (teacher.id === this.teacher.id) { this.teacherSelect.setValue(teacher); } } ✚ }); }); } ``` * 只有当传入teacher时,才进行赋值。 除此以外,我们还可以使用更优化的如下方案: ``` /** * 获取所有的教师,并传给V层 */ ngOnInit() { this.teacherSelect = new FormControl(this.teacher); ➊ const url = 'http://localhost:8080/Teacher'; this.httpClient.get(url) .subscribe((teachers: Array<Teacher>) => { this.teachers = teachers; }); } /** * 比较函数,标识用哪个字段来比较两个教师是否为同一个教师 * @param t1 源 * @param t2 目标 */ compareFn(t1: Teacher, t2: Teacher) { ➋ return t1 && t2 ? t1.id === t2.id : t1 === t2; } ``` * ➊ 直接使用teacher进行初始化 * ➋ 定义实体比较函数。即:当两个实体的id相等时,我们认为这两个实体是一样的 然后将此`compareFn`方法对应添加到V层: ``` <select id="teacherSelect" [formControl]="teacherSelect" (change)="onChange()" [compareWith]="compareFn" ➊> <option *ngFor="let teacher of teachers" [ngValue]="teacher"> {{teacher.name}} </option> </select> ``` * ➊ 定义判断两个对象是否相等的方法(当两个对象的ID相同时便认为这两个对象是相等的) ![](https://img.kancloud.cn/81/be/81bed0308267ea1e54648385466400a8_478x386.png) 整体测试通过,其中有一个警告(黄色的点),我们暂时不理它。 > 在教程的4.7.7小节中对为何要使用compareWith进行判断进行简单的说明 ## 错误的导航 在班级新增及班级编辑组件中,我们点击完确认按钮后没有如我们期望的跳转到班级列表而是跳转到了首页。在一些资料的查找中,笔者并没有找到更好的解决方案及该错误的产生的原因。虽然在我们也可以通过更正规的方法来解决这个问题,但在此我们仍然采用暴力的`hard code`方法来临时解决下这个问题。 我们将班级新增及编辑中进行跳转的代码临时改为: ``` this.router.navigateByUrl('', {relativeTo: this.route}); ✘ this.router.navigateByUrl('/klass'); ✚ ``` # 参考文档 | 名称 | 链接 | 预计学习时长(分) | | --- | --- | --- | | 源码地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step3.5.7](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step3.5.7) | - | | SelectControlValueAccessor | [https://www.angular.cn/api/forms/SelectControlValueAccessor](https://www.angular.cn/api/forms/SelectControlValueAccessor) | 15 |