---
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