#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')