برنامه نویسی

نحوه نوشتن تست های واحد برای سرویس های Backend با وابستگی های پایگاه داده با استفاده از SQLite In-Memory

معرفی

هنگام توسعه خدمات باطن، تست واحد برای اطمینان از صحت و ثبات کد شما بسیار مهم است. با این حال، نوشتن آزمون‌های واحد برای مؤلفه‌هایی که با پایگاه داده تعامل دارند، می‌تواند چالش برانگیز باشد. استفاده از یک پایگاه داده واقعی برای آزمایش می تواند کند و دست و پا گیر باشد و می تواند عوارض جانبی ایجاد کند که تکرار آزمایش ها را دشوار می کند. یک راه حل موثر، استفاده از پایگاه داده SQLite در حافظه است که راه اندازی سریع و آسان است و امکان جداسازی و تکرار تست ها را فراهم می کند.

در این مقاله، نحوه پیکربندی و نوشتن تست‌های واحد را برای یک سرویس پشتیبان که با پایگاه داده تعامل دارد، با استفاده از TypeORM و SQLite درون حافظه بررسی خواهیم کرد.

نصب وابستگی ها

ابتدا باید وابستگی های لازم را نصب کنیم:

npm install --save-dev typescript ts-jest ts-node @types/jest @types/node jest sqlite3 typeorm reflect-metadata
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پیکربندی محیط تست

فایل پیکربندی TypeORM برای آزمایش

یک فایل پیکربندی TypeORM خاص برای آزمایش ایجاد کنید. این فایل TypeORM را برای استفاده از پایگاه داده SQLite در حافظه پیکربندی می کند.

jest.setup.ts

import 'reflect-metadata';
import {
  createConnection,
  getConnection,
} from 'typeorm';
import { User } from './src/entity/User';

beforeAll(() => {
  return createConnection({
    type: 'sqlite',
    database: ':memory:',
    dropSchema: true,
    entities: [User],
    synchronize: true,
    logging: false,
  });
});

afterAll(async () => {
  const connection = getConnection();
  await connection.close();
});

afterEach(async () => {
  const connection = getConnection();
  await connection.synchronize(true);
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ساختار پروژه

فرض کنید ساختار پروژه زیر را دارید:

src/
  entity/
    User.ts
  repository/
    UserRepository.ts
  service/
    UserService.ts
  __tests__/
    UserService.test.ts
  jest.setup.ts
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پیاده سازی ماژول ها

src/entity/User.ts

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id!: number;

  @Column()
  name!: string;

  @Column()
  email!: string;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

src/repository/UserRepository.ts

import { EntityRepository, Repository } from 'typeorm';
import { User } from '../entity/User';

@EntityRepository(User)
export class UserRepository extends Repository<User> {
  findByName(name: string): Promise<User | undefined> {
    return this.findOne({ name });
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

src/service/UserService.ts

import { getCustomRepository } from 'typeorm';
import { UserRepository } from '../repository/UserRepository';
import { User } from '../entity/User';

export class UserService {
  private userRepository = getCustomRepository(UserRepository);

  async findUserByName(name: string): Promise<User | undefined> {
    return this.userRepository.findByName(name);
  }

  async createUser(name: string, email: string): Promise<User> {
    const user = new User();
    user.name = name;
    user.email = email;
    return this.userRepository.save(user);
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

تست پیکربندی با Jest

یک فایل پیکربندی Jest ایجاد کنید تا مطمئن شوید که محیط تست شما به درستی پیکربندی شده است.

jest.config.js

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  setupFilesAfterEnv: ['./jest.setup.ts'],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  testPathIgnorePatterns: ['/node_modules/', '/dist/'],
  transform: {
    '^.+\\.(ts|tsx)$': 'ts-jest',
  },
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.json',
    },
  },
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پیکربندی TypeScript

از پیکربندی TypeScript اطمینان حاصل کنید (tsconfig.json) امکان استفاده از دکوراتورها و فراداده های دکوراتور را می دهد.

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "lib": ["ES2020"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": "node",
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "**/*.test.ts", "dist"]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

تست نویسی

src/__tests__/UserService.test.ts

import { UserService } from '../service/UserService';

describe('UserService', () => {
  let userService: UserService;

  beforeAll(() => {
    userService = new UserService();
  });

  test('should create a new user', async () => {
    const user = await userService.createUser('John Doe', 'john@example.com');
    expect(user).toHaveProperty('id');
    expect(user.name).toBe('John Doe');
    expect(user.email).toBe('john@example.com');
  });

  test('should find a user by name', async () => {
    const user = await userService.createUser('Jane Doe', 'jane@example.com');
    const foundUser = await userService.findUserByName('Jane Doe');
    expect(foundUser).toBeDefined();
    expect(foundUser?.name).toBe('Jane Doe');
    expect(foundUser?.email).toBe('jane@example.com');
  });

  test('should return undefined if user is not found', async () => {
    const foundUser = await userService.findUserByName('Non Existent');
    expect(foundUser).toBeUndefined();
  });
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیح

  1. تست پیکربندی پایگاه داده:

    • ما TypeORM را برای استفاده از پایگاه داده SQLite در حافظه برای آزمایش پیکربندی کردیم.
    • jest.setup.ts برای ایجاد اتصال پایگاه داده قبل از همه آزمایش ها و بستن آن پس از همه آزمایش ها استفاده می شود.
  2. همگام سازی پایگاه داده:

    • پس از هر تست، پایگاه داده را همگام سازی می کنیم تا داده های وارد شده در طول آزمایش پاک شود (await getConnection().synchronize(true);).
  3. تست نویسی:

    • ما تست هایی ایجاد می کنیم تا بررسی کنیم که کاربر به درستی ایجاد شده است، کاربر با نام پیدا شده است و کاربر برمی گردد. undefined زمانی که کاربر پیدا نشد

نتیجه

استفاده از پایگاه داده SQLite در حافظه برای آزمایش، یک راه عالی برای آزمایش عملکرد است که به یک پایگاه داده واقعی بدون پیچیدگی راه اندازی یک پایگاه داده آزمایشی جداگانه بستگی دارد. این تضمین می کند که تست ها سریع، ایزوله و قابل اعتماد هستند. با این رویکرد، می توانید اطمینان حاصل کنید که کد شما به درستی با پایگاه داده تعامل دارد و تمام عملکردهای حیاتی تأیید شده است.

مخزن

https://github.com/vitorrios1001/tests-with-db

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا