成功的对表单进行输入后,本节我们开始按规范开发数据的提交功能。 ## 提交班级信息 ``` export class AddComponent implements OnInit { /*当发生请求错误时,显示该信息*/ public static errorMessage = '数据保存失败,这可能是由于网络的原因引起的'; name: FormControl; teacherId: FormControl; /*当该值不为空时,可以显示在前台并提示用户*/ message: string; constructor(private httpClient: HttpClient) { } ngOnInit() { this.name = new FormControl(''); this.teacherId = new FormControl(); } onSubmit(): void { const url = 'http://localhost:8080/Klass'; const klass = new Klass(undefined, this.name.value, new Teacher(parseInt(this.teacherId.value➊, 10), undefined, undefined) ); this.httpClient.post(url, klass) .subscribe(() => { console.log('保存成功'); }, (response) => { console.log(`向${url}发起的post请求发生错误` + response); this.setMessage(AddComponent.errorMessage); }); } /** * 使用传的值来设置message,并在1.5秒后将消息置空 * @param message 消息 */ private setMessage(message: string): void { this.message = message; setTimeout(() => { this.message = ''; }, 1500); } } ``` * ➊ FormController获取的值的类型为string,Teacher中的ID的类型为number。使用parseInt(字符串,进制)将字符串转为number使类型相匹配。 ## 测试 我们测试点保存按钮点击后,组件是否按预期提交了相应的请求: klass/add/add.component.spec.ts ``` /** * 设置表单数据 * 点击按钮发起请求 * 断言:请求地址、请求方法、请求主体数据 */ fit('保存按钮点击后,提交相应的http请求', () => { httpTestingController = TestBed.get(HttpTestingController); expect(component).toBeTruthy(); component.name.setValue('test3'); component.teacherId.setValue('3'); fixture.whenStable().then(() => { const debugElement: DebugElement = fixture.debugElement; const submitButtonElement = debugElement.query(By.css('button')); const submitButton: HTMLButtonElement = submitButtonElement.nativeElement; submitButton.click(); const req = httpTestingController.expectOne('http://localhost:8080/Klass'); expect(req.request.method).toEqual('POST'); ➊ const klass: Klass = req.request.body.valueOf(); ➋ console.log(klass);➌ expect(klass.name).toEqual('test3');➍ expect(klass.teacher.id).toEqual(3);➍ }); }); ``` * ➊ 断言请求方法为POST * ➋ 获取请求主体数据 * ➌ 在终端及浏览器控制中中打印klass数据信息 * ➍ 断言成功传入了名称及教师ID ``` LOG: Klass{id: undefined, name: 'test3', teacher: Teacher{id: 3, name: undefined, username: undefined, email: undefined, sex: undefined}} ➊ Chrome 78.0.3904 (Mac OS X 10.13.6): Executed 1 of 10 SUCCESS (0 secs / 0.258 secs) LOG: Klass{id: undefined, name: 'test3', teacher: Teacher{id: 3, name: undefined, username: undefined, email: undefined, sex: undefin➋ Chrome 78.0.3904 (Mac OS X 10.13.6): Executed 1 of 10 (skipped 9) SUCCESS (3.672 secs / 0.258 secs) TOTAL: 1 SUCCESS TOTAL: 1 SUCCESS ``` * ➊ 终端中打印的测试数据 * ➋ 浏览器打印日志 ![](https://img.kancloud.cn/f9/fa/f9fadf9c319b09a6a0589b5e41ac7622_522x460.png) ## 模拟响应数据 klass/add/add.component.spec.ts ``` expect(klass.name).toEqual('test3'); expect(klass.teacher.id).toEqual(3); req.flush(null➊, {status: 201➋, statusText: 'Created'➌}); ✚ }); ``` * ➊ 返回空数据。 * ➋ 新增成功,返回状态码201(行业惯例)。 * ➌ 返回对状态码的说明。 测试: ``` LOG: Klass{id: undefined, name: 'test3', teacher: Teacher{id: 3, name: undefined, username: undefined, email: undefined, sex: undefined}} Chrome 78.0.3904 (Mac OS X 10.13.6): Executed 1 of 10 SUCCESS (0 secs / 0.097 secs) LOG: Klass{id: undefined, name: 'test3', teacher: Teacher{id: 3, name: undefined, username: undefined, email: undefined, sex: undefinLOG: '保存成功' Chrome 78.0.3904 (Mac OS X 10.13.6): Executed 1 of 10 SUCCESS (0 secs / 0.097 secs) Chrome 78.0.3904 (Mac OS X 10.13.6): Executed 1 of 10 (skipped 9) SUCCESS (0.121 secs / 0.097 secs) TOTAL: 1 SUCCESS TOTAL: 1 SUCCESS ``` > 最后,我们将测试完毕的方法名由`fit`变更为`it`。 # 参考文档 | 名称 | 链接 | 预计学习时长(分) | | --- | --- | --- | | 源码地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step3.3.2](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step3.3.2) | - | | 测试http请求 | [https://www.angular.cn/guide/http#testing-http-requests](https://www.angular.cn/guide/http#testing-http-requests) | 10 | | TestRequest | [https://www.angular.cn/api/common/http/testing/TestRequest#request](https://www.angular.cn/api/common/http/testing/TestRequest#request) | 5 |