2016-11-11 5 views
2

Мне было интересно, есть ли способ в Guice переопределить привязку с помощью прослушивателей или перехватчиков, прежде чем он будет создан.Перезаписать конкретное связывание guice через перехватчик или прослушиватель или препроцессор

Мой сценарий:

У меня есть модуль А, который связывает клиента, например:

public static class ProdModule extends AbstractModule { 
     @Override 
     protected void configure() { 
      bind(Client.class).toInstance(ClientBuilder.newBuilder().build()); 
     } 
    } 

Это обязательные потребности быть высмеивал. Поэтому я хотел бы, чтобы тест добавил новый модуль, который регистрирует Listener (или что-то еще), так что, когда Guice пытается решить эту привязку, я могу заменить ее любым необходимым связыванием.

Я знаю о Modules.override(...), однако это не может использоваться с моей настройкой. Код, создающий экземпляр Инжектора, похоронен в зависимости, по существу. У меня нет доступа к изменению кода для использования перезаписываемых модулей, однако я могу добавить столько новых модулей, сколько захочу.

Я не хочу заменять весь модуль и вообще не хочу изменять код модуля.

Я пытался несколько вещей, которые либо не работают, или я не знаю, как их использовать:

Я попытался с помощью ProvisionListener. Это работало «несколько». Я мог бы перезаписать конкретного поставщика, используя отражение и изменение поля результата в Provision. Это не работает, например, привязки.

Я пробовал использовать ElementVisitor и BindingTargetVisitor, однако они ничего не сделали для меня. Возможно, я не понимаю, в чем заключается цель этих двух посетителей, и я не нашел слишком много документации или примеров.

+1

От того, как вы описали свои ограничения, нет никакого способа сделать это. –

+0

@TavianBarnes спасибо. Я боялся, что это так. В настоящее время я пытаюсь обойти свои ограничения, чтобы использовать Modules # override – pandaadb

+0

"* Я не хочу заменять весь модуль и не хочу вообще изменять код модуля. *" - почему бы и нет? Разве это не ваш код? Или вы просто пытаетесь избежать рефакторинга своих модулей? – dimo414

ответ

1

Похоже, вы собираетесь об этой проблеме в обратном направлении - инъекции зависимость существует, чтобы включить тестирование, так что если вы изо всех сил, чтобы написать тестируемый код при использовании рамки DI это стоит отступив и выяснить, что случилось в более высокий уровень, вместо того, чтобы пытаться бороться с каркасом, вести себя так, как вы думаете.

"Это обязательное обложение должно быть издевательством." - большой красный флаг. Вам почти не нужно связывать объекты mocks, потому что макеты являются хрупкими и обычно предназначены для использования в одноцелевых модульных тестах, не предусмотренных каркасом DI в приложении.

Если вы пишете единичный тест, вам не понадобится фреймворк вообще - просто создайте экземпляр класса под тестом напрямую, передав необходимые макеты. Благодаря внедрению зависимостей вы должны иметь возможность быстро тестировать класс изолированно, если все его зависимости вычеркнуты - никакой рамки не требуется.

Если вы пишете интеграцию или другой более крупный тест и, следовательно, необходимо сконструировать инжектор и протестировать систему в целом, в идеале вы должны иметь поддельные (не макетные) реализации компонентов, которые нельзя безопасно протестировать, и альтернативные модули для установки для таких тестов. Например, ваш тестовый инжектор установит FakeCreditCardProcessorModule вместо CreditCardProcessorModule, а модули, обеспечивающие привязки, которые вы пытаетесь протестировать, достаточно слабо связаны, чтобы не заботиться о том, какой процессорный модуль установлен. Если это не опция из-за слишком связанных модулей, то Modules.override() может использоваться для подделки отдельных привязок.

Только если вы тестируете логику модуля, если вы хотите связать насмешки (хотя, как правило, не рекомендуется использовать сложную логику, заслуживающую тестирования в ваших модулях). Вы должны установить только тестируемый модуль вместе с отдельным модулем, который связывает макеты для любых необходимых привязок. Это единственное время, когда на самом деле мошенники действительно имеют смысл с картой DI.

Если ни один из вышеперечисленных сценариев не применяется, пожалуйста, предоставьте более подробную информацию о , что вы пытаетесь протестировать.

+0

Привет, спасибо за ваш ответ. Я считаю, что это интеграционный тест. Я согласен со всем, что вы сказали. Одна из моих проблем заключалась в том, что я не хотел создавать поддельные модули (например, если что-то в самом модуле prod изменяется, поддельный модуль пропустит это). Поэтому я хотел оставить приложение отдельно, но специально заменить только один класс (клиент в этом случае). Мысль о поддельном клиенте, но это не так просто, как замена java bean, поэтому я думал, что это насмехается, это избавит меня от некоторых головных болей. – pandaadb

+0

Если что-то в модуле prod изменяется, ваши тесты этого модуля должны начинаться с сбоя (например, из-за отсутствия привязки), поэтому это должно быть в целом. В идеале ваши модули представляют собой четко разделенные компоненты (например, модуль базы данных), которые обеспечивают определенные привязки, что позволяет легко вводить поддельные модули, которые обеспечивают одинаковые привязки. Если это не представляется возможным, возможно, ваш модуль (ы) слишком сложный, и вам будет полезно разделить их на более мелкие, более логически различные компоненты. – dimo414

+0

Вот что я в итоге сделал. во-первых, разделить модуль на более мелкие более конкретные, а для конкретных привязок, которые я хотел бы переопределить, ввести методы, возвращающие экземпляр, и их можно перезаписать. Таким образом, мой поддельный модуль мог бы расширить мой модуль prod, а затем просто заменить нужное мне значение – pandaadb