Как предоставить MockService в разработке с Nest.js ?

#javascript #node.js #typescript #dependency-injection #nestjs

#javascript #node.js #typescript #внедрение зависимостей #nestjs

Вопрос:

У меня есть класс MailService и класс MailMockService , который следует использовать в разработке.

Согласно документации Nest, это должно работать следующим образом:

app.module.ts

 @Module({
  imports: [...],
  controllers: [...],
  providers: [
    ...,
    {
      provide: MailService,
      useClass: (process.env.NODE_ENV === 'development') ? MailMockService : MailService,
    },
  ],
})
export class AppModule {
}
  

Однако это работает не так, как ожидалось. process.env.NODE_ENV равно 'development' , но модуль по-прежнему предоставляет класс MailService .

Как я могу заставить модуль предоставлять MailMockService в зависимости от среды?

Редактировать:

Я использую сервис следующим образом:

 import { MailService } from './mail/mail.service';
...
const mailService = new MailService();
  

Я думаю, что import обходит предоставленный MailService / MailMockService из Module (код все еще работает без объекта в providers массиве). Но как я могу указать программе использовать MailMockService ?

Комментарии:

1. Это также не сработает, если вы замените process.env.NODE_ENV на true ? Вы предоставляли MailService несколько раз?

2. @KimKern Пожалуйста, посмотрите мой отредактированный вопрос.

3. MailService Должен быть создан фреймворком, которого нет в вашем коде, см. Мой ответ. Где вы используете MailService и есть ли причина, по которой вы его не внедрили?

4. Мне любопытно, почему вы хотели бы использовать другой сервис между производством и разработкой. В любом случае, не могли бы вы просто сделать что-то вроде: const mailerSvc = process.env.NODE_ENV === ‘DEV’ ? require(‘путь /к / макету’) : require(‘путь / к / реальной / вещи’)

5. @Pytth Я реализовал это именно так, но а) мне кажется неправильным иметь mockservice внутри контроллера и б) Мне любопытно, как @Module работает подробно 🙂

Ответ №1:

Если вы создаете экземпляр сервиса самостоятельно вместо использования внедрения зависимостей nest, вы нарушаете цель фреймворка.

Но как я могу указать программе использовать MailMockService ?

Это именно то, что делает внедрение зависимостей таким замечательным: вы можете управлять зависимостями, которые используются в ваших единицах (классах, модулях, …), не изменяя сами эти единицы. Отлично подходит для тестирования или специфики среды, как в вашем случае.

Таким образом, класс, который использует MailService , должен быть создан фреймворком и затем может внедрить MailService с помощью:

 constructor(private mailService: MailService) {}
  

Затем будет использоваться экземпляр, который предоставляется в вашем providers массиве.


Если это невозможно, вы, конечно, можете использовать логику в самих классах-потребителях (не очень приятно!):

 const mailService = process.env.NODE_ENV === 'development' 
                    ? new MailMockService()
                    : new MailService();
  

Ответ №2:

Вот как я бы это сделал:

 const mailerSvc = process.env.NODE_ENV === 'DEV' 
    ? require('path/to/mock')
    : require('path/to/real/thing')