Integration with Data Generation Tools
This chapter will teach you how to integrate data generation tools to encapsulate custom decorators, making your code more concise and elegant, and use data generation tools to implement business mock functionality.
Project Structure Preparation
bash
project
├── api
│ ├── common
│ │ └── index.ts # Common interface decorators
│ └── userApi.ts # Real interface classes
└── mock
├── common
│ └── index.ts # Common methods
├── models
│ └── userModel.ts # Define data models
└── userMock.ts # Encapsulated user mock decoratorsDefine Data Models
Data models are defined using data-faker-plus in /mock/models/userModel.ts
ts
import { DataField, DataModel, defineModel, faker } from 'data-faker-plus';
// Define user data model
@DataModel('user')
export class UserModel {
@DataField('string.uuid')
declare id: string;
@DataField('person.firstName')
declare firstName: string;
@DataField('person.lastName')
declare lastName: string;
@DataField(['number.int', { min: 1, max: 120 }])
declare age: number;
@DataField(ctx => {
return faker.internet.email({ firstName: ctx.firstName, lastName: ctx.lastName });
})
declare email: string;
@DataField('phone.number')
declare phone: string;
@DataField('person.sex')
declare sex: string;
}data-faker-plus
I recommend using data-faker-plus for data simulation. For usage of data-faker-plus, please refer to:
Encapsulate Mock Decorators
Define Common Methods
/mock/common/index.ts defines common error handling methods
ts
/**
* Common methods
*/
import { HttpResponse } from 'msw';
/**
* Network error
* @returns
*/
export function netWorkError() {
return HttpResponse.error();
}Define User Mock Decorators
/mock/userMock.ts defines user-related mock decorators
ts
import { HttpResponse, Mock, MockHandlers } from '@/index';
import { fakeData, useModel } from 'data-faker-plus';
import { UserModel } from './models/userModel';
import { netWorkError } from './common';
// Use data-faker-plus to generate fake data
const users = fakeData(useModel(UserModel), 30);
/**
* Mock user pagination
*/
export function MockUserPages() {
let handlers = {
default: () => {
return HttpResponse.json({
message: 'success',
data: users,
});
},
error: netWorkError,
};
return Mock(handlers);
}
/**
* Mock delete user
*/
export function MockUserDelete() {
let handlers: MockHandlers = {
default: ({ params }) => {
// Get user parameters
const { id } = params;
// Find user
const user = users.find((item: any) => item.id === id);
// Delete user
users.splice(users.indexOf(user), 1);
// Return success message
return HttpResponse.json({
message: 'delete success',
});
},
error: netWorkError,
};
return Mock(handlers);
}
/**
* Mock update user
*/
export function MockUserUpdate() {
// Success handler
const success: MockHandlers = async ({ request }) => {
// Get request body parameters
let user = await request.json();
user = JSON.parse(JSON.stringify(user)) as UserModel;
if (!user || !user.id) {
return HttpResponse.json({
status: 400,
message: 'params error',
});
}
// Update user information
const index = users.findIndex((item: any) => item.id === user.id);
users[index] = user;
return HttpResponse.json({
message: 'update success',
});
};
// Error handler
const error = netWorkError;
// Return Mock decorator
return Mock({
default: success,
error,
});
}
/**
* Add user
*/
export function MockUserCreate() {
// Success handler
const success: MockHandlers = async ({ request }) => {
// Get request body parameters
let user = await request.json();
// Add new user
users.unshift(user);
return HttpResponse.json({
message: 'create success',
});
};
// Error handler
const error = netWorkError;
// Return Mock decorator
return Mock({
default: success,
error,
});
}Encapsulate Interface Decorators
/api/common/index.ts
ts
import { HttpMethodDecoratorConfig, Post } from '@/index';
/**
* Pagination query decorator
* @param config Request configuration
* @returns Post decorator
*/
export function Pages(config: HttpMethodDecoratorConfig) {
config.headers = {
'Content-Type': 'application/json',
};
return Post(config);
}Define Real Interface Classes
/api/userApi.ts
ts
import { Delete, Get, Post, Put } from '@/core/httpMethod';
import { HttpApi } from '@/core/ioc';
import { Pages } from './common';
import { BodyParam, PathParam } from '@/core/params';
import { MockUserCreate, MockUserDelete, MockUserPages, MockUserUpdate } from '../mock/userMock';
@HttpApi({
baseURL: 'http://localhost:3000/api/users',
mock: {
on: true,
condition: () => {
return process.env.NODE_ENV === 'test';
},
},
})
class UserApi {
/**
* User pagination query interface
* @param page Page number
* @param size Page size
*/
@Pages({ url: '/pages/:page/:size' })
@MockUserPages()
getUserPages(@PathParam('page') page: number, @PathParam('size') size: number): any {}
/**
* Delete user interface
* @param id User ID
*/
@Delete('/:id')
@MockUserDelete()
deleteUser(@PathParam('id') id: number): any {}
/**
* Add user interface
*/
@Post('/')
@MockUserCreate()
addUser(@BodyParam() user: { name: string; age: number }): any {}
/**
* Update user interface
*/
@Put('/')
@MockUserUpdate()
updateUser(@BodyParam() user: { id: number; name: string; age: number }): any {}
}
export const userApi = new UserApi();Test Interface Calls
Turn on the mock switch to test if the interfaces work properly
ts
// Must enable mock switch first
MockAPI.on();
const { data } = await userApi.getUserPages(1, 10)();
console.log(data);
// Delete user
const { data: data2 } = await userApi.deleteUser(1)();
console.log(data2);
// Add user
const { data: data3 } = await userApi.addUser({ name: 'test', age: 18 })();
console.log(data3);