У меня есть такой интерфейс:
public interface DateTimeService {
ZonedDateTime now();
void fixTo(ZonedDateTime date);
void forget();
}
, и у меня есть две его реализации.Один для производства, где fixTo
и forget
генерирует исключения, а другой для тестирования, где мы контролируем время.Затем у меня есть конфигурация CDI, которая в зависимости от флага создает правильный тип.
@ApplicationScoped
public class Configuration {
@Produces
@ApplicationScoped
public DateTimeService dateTimeService(Configuration config) {
if (config.isFakeDateTimeServiceEnabled()) {
return new FakeDateTimeService();
} else {
return new DefaultDateTimeService();
}
}
}
Однако я хотел удалить fixTo
и forget
из DateTimeService
, поскольку они есть только там, поэтому мы можемконтрольное время в тестах.Я сделал новый интерфейс, например:
public interface FakeDateTimeService extends DateTimeService {
// fixto and forget is moved from DateTimeService to here
}
У меня есть несколько точек ввода.Некоторые в рабочем коде, некоторые в тестовом кодеВ рабочем коде я хотел бы иметь возможность доступа только к DateTimeSerice
, в тестовом коде я хочу иметь возможность получить указатель на расширенный сервис.
В коде продукта:
@Inject
private DateTimeService dateTimeService;
В тестовом коде:
@Inject
private FakeDateTimeService dateTimeService;
Если я оставлю конфигурацию без изменений, то тестовый код никогда не найдет мою расширенную службу (поскольку CDI, похоже, игнорирует тип времени выполнения экземпляра, созданного методом продюсера).
Если я обновлю конфигурацию для создания экземпляров обоих (в этом случае я даже могу внедрить подлинную службу в поддельную), тогда производство не сможет соединиться, так как в fake также реализован интерфейс DateTimeService
, и это вызываетнеоднозначность.В этот момент я, вероятно, мог бы просто использовать квалификатор, но я не хочу менять свой производственный код из-за этого и не должен иметь поддельную службу времени и даты в производственном контексте.
Я пытался наложить вето на создание бина, ноЯ не смог этого сделать.
Я думал, что сработает / должен работать, это создать экземпляр правильного типа и программно добавить его в контекст компонента, но я нашел примеры для CDI 2.0, в то время как на данный момент соответствующая часть моего кодазастрял на CDI 1.2.
Возможно, в этот момент вы можете сказать, что я не эксперт CDI.Так что я открыт для предложений о хороших материалах для чтения CDI, а также конкретных предложений по этой проблеме.
В противном случае, я собираюсь сдаться и просто жить с DateTimeService
, которые имеют fixTo
иforget
методов.