--- tags: [angular, test] --- # Unit Testing (Jest) > VSCode tool , 可以直接幫忙你測試一個 `test` ,不用在 npm run test [https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest](https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest) 提示寫法 [https://marketplace.visualstudio.com/items?itemName=andys8.jest-snippets](https://marketplace.visualstudio.com/items?itemName=andys8.jest-snippets) > ## Basic toBeTruthy():確認是為為 true 如果為 false, 0, '',null , undefine, NaN,為false [Expect · Jest](https://jestjs.io/docs/expect#tobetruthy) expect 系列,相關的 function [前端測試框架Jest系列教程 -- Expect(驗證)](https://www.twblogs.net/a/5b8fe1972b7177672215f095) **toHaveBeenCalledWith():** 可以多看 ssr 專案中 notifications ,`should send get /config/getNotifications` ```tsx it('should send get /config/getNotifications', () => { const apiSpy = jest.spyOn(apiService, 'get'); // apiService 打 api-service service.getNotifications(); expect(apiSpy).toHaveBeenCalledWith('/config/getNotifications'); }); ``` **mockReturnValue():** Accepts a value that will be returned whenever the mock function is called. 可以 return 所設定的值 ```jsx jest.spyOn(apiService, 'post').mockReturnValue( throwError({ error: { // email已經存在 ReturnCode: 40032, }, }) ); ``` ## 測試環境下拿到 component 實體 ```tsx import { HeaderLeftComponent } from './header-left.component'; describe('HeaderLeftComponent', () => { let fixture: ComponentFixture<HeaderLeftComponent>; // const component = fixture.componentInstance it('test sum function', () => { expect(fixture.componentInstance.sum(1, 2)).toBe(3); }); } ``` ```tsx // click 的寫法 fixture = TestBed.createComponent(HeaderLeftComponent); const menu = fixture.debugElement.nativeElement.querySelector('header-hamburger'); menu.click(); ... expect(...).toBe(...) ``` call service 的 function 來用 ```tsx const video = { play() { return true; }, }; module.exports = video; // const video = require('./video'); test('plays video', () => { const spy = jest.spyOn(video, 'play'); const isPlaying = video.play(); expect(spy).toHaveBeenCalled(); expect(isPlaying).toBe(true); spy.mockRestore(); // 為了要回復狀態用的 }); ``` [The Jest Object · Jest](https://jestjs.io/docs/jest-object#jestspyonobject-methodname) ## 非同步測試 [Jest:非同步測試](https://titangene.github.io/article/jest-async-test.html) ## 測試場景 ## QA Q:What is the difference between `it` and `test` in Jest ? 看起來是一樣的東西 [What is the difference between 'it' and 'test' in Jest?](https://stackoverflow.com/questions/45778192/what-is-the-difference-between-it-and-test-in-jest) ## 引用物件的東西 ```jsx jest.spyOn(object, methodName) ``` [The Jest Object · Jest](https://jestjs.io/docs/jest-object#jestspyonobject-methodname) ## reference [十分鐘上手前端單元測試 - 使用 Jest](https://wcc723.github.io/development/2020/02/02/jest-intro/) jest function [JEST 單元測試學習筆記 | Mock Functions](https://medium.com/unalai/jest-%E5%96%AE%E5%85%83%E6%B8%AC%E8%A9%A6%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-mock-functions-4dfe8804f2c0) 寫 unit test 的想法 [91 的 Unit Test實戰營心得](https://andyludeveloper.medium.com/91-%E7%9A%84-unit-test%E5%AF%A6%E6%88%B0%E7%87%9F%E5%BF%83%E5%BE%97-5dd3c06d5e36) [引入完整的 angular ](https://www.notion.so/angular-2052be9ff61f49d5b89b92b160e4411b) ## 如果有引用 dialog 時 ```jsx TestBed.configureTestingModule({ declarations: [GeneralDialogComponent], imports: [ MatDialogModule, HttpClientModule, BrowserModule, TranslateModule.forRoot({}), // pipe 'translate' RouterTestingModule.withRoutes([]), GoogleTagManagerModule.forRoot({ id: environment.tagManagerID, }), BrowserAnimationsModule, ], }).overrideModule(BrowserModule, { set: { entryComponents: [GeneralDialogComponent], }, }); // 需要加 overrideModule ``` ## 身份認證的寫法 可以去看 auth.spec.ts 的寫法 ```jsx import { ApiService } from './api.service'; import { ApiSystemService } from './api/api-system.service'; import { AuthService } from './auth.service'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { TestBed } from '@angular/core/testing'; import { of } from 'rxjs'; describe('AuthService', () => { let service: AuthService; let apiService: ApiService; let apiSystemService: ApiSystemService; let apiSpy = null; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule, RouterTestingModule.withRoutes([])], providers: [ApiService], }); service = TestBed.inject(AuthService); apiService = TestBed.inject(ApiService); apiSystemService = TestBed.inject(ApiSystemService); apiSpy = jest.spyOn(apiSystemService, 'getCheckAuth').mockReturnValue( of({ data: { config: { user: { id: '1', timezone: '+8' }, supplier: { id: '2', status: 'Inactive' }, }, }, }) ); }); it('should be created', () => { expect(service).toBeTruthy(); }); it('should send get /config/checkAuth', () => { service.initUserRoles(); expect(apiSpy).toBeCalledTimes(1); }); it('should get userId', () => { service.initUserRoles(); expect(service.userId).toBe('1'); }); it('should get supplierId', () => { service.initUserRoles(); expect(service.supplierId).toBe('2'); }); it('should get userTimezone', () => { service.initUserRoles(); expect(service.userTimezone).toBe('+8'); }); it('should get isLogin', () => { service.initUserRoles(); expect(service.isLogin()).toBeTruthy(); }); it('should get isActiveSupplier', () => { service.initUserRoles(); expect(service.isActiveSupplier()).toBeFalsy(); }); }); ``` ## 正規驗證可以看 validation.server.spec.ts