NestJS + Prisma Testing with Test database
Published: 2022-12-11 04:52:14

Hello! My Dev friends!

I found a job few month ago, I took a back-office project, It was very good opportunity to make test environment and write a test code.

So, I want to archiving personal experience and share with you how did I implemented testing environment.

I made NestJS + PrismaORM for back-office server, But This structure was major challenge for me when make test environment.

First of all, NestJS official docs recommend using TypeORM.

TypeORM can mocking in test code, But Prisma is not.
Prisma also supported unit testing and mocking, but it's little lack something.

For example, my service logic(business logic) has Prisma Service (Wrapped PrismaClient with @Injectable decorator) dependency, But it cannot inject inside business logic in test code.

NestJS with `@nestjs/testing` library allow to make a test module in test code.

Here's my code

`auth.service.ts`
```typescript
@Injectable()
export class AuthService {
  constructor(
    private backofficePrisma: PrismaBackofficeService,
    private jwtService: JwtService
  ) {}

// AuthService has a Prisma service dependency.

...
```

`auth.service.spec.ts`
```typescript

describe("AuthService", () => {
  let service: AuthService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [AuthModule, ServiceModule],
      providers: [AuthService, JwtService],
    }).compile();

    service = module.get<AuthService>(AuthService);
  });

  it("Auth Service should be defined", () => {
    expect(service).toBeDefined();
  });
});

```

I want to simple test auth service.
So I wrote a code like this.

```typescript
it("Sign up should be return User model without password", async() => {
    const userCreateDto = {
      email : "user@example.com",
      password : "abcdef1234"
    }

    const userCreatedDate = new Date();
    const user = await service.signUp(userCreateDto);

    expect(user.email).toMatch(userCreateDto.email);
    expect(user).toHaveProperty('crated');
    expect(user).toHaveProperty('updated');
  })

```

above code not explain how mocking PrismaClient, But I actually did it, but not works.

Because, Mocking Prisma same as Mocking PrismaClient, not a PrismaService

So I failed this way.

I tried to another way. just make a test database using docker.

First I wrote a docker-compose.yml
```yml
//...

test:
    command: mysqld --character-set-server=utf8 --collation-server=utf8_general_ci
    container_name: test-backoffice
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 1
    image: mysql
    ports:
      - "3307:3306"

```

and setting .env.test
```text

DATABASE_URL="mysql://root@localhost:3307/backoffice"

JWT_SECRET="your_auth_secrets"

```

also setting package.json for yarn command

```package.json
"test:watch": "dotenv -e .env.test -- jest --watch --config jest-int.json",

```

As you can see a `jest-int.json`
like down below

```json
{
  "moduleFileExtensions": ["js", "json", "ts"],
  "rootDir": ".",
  "testRegex": ".*\\.spec\\.ts$",
  "transform": {
    "^.+\\.(t|j)s$": "ts-jest"
  },
  "collectCoverageFrom": ["**/*.(t|j)s"],
  "coverageDirectory": "../coverage",
  "testEnvironment": "node",
  "moduleNameMapper": {
    "src/(.*)": "<rootDir>/src/$1"
  }
}
```


And just run command `yarn run test:watch` and works very well.


It seems like very ugly way.

If you have a method about test business logic with inject mocking prisma without making test db, Please share me..

If I find a new good method, I will share it also.

Thanks for reading. Whatever, whenever I will appreciate your criticizing of code or method.