Guice 바인딩 덮어쓰기
이제 막 Guice를 사용하기 시작했는데, 제가 생각할 수 있는 사용 사례는 테스트에서 단일 바인딩을 덮어쓰는 것입니다.나머지 프로덕션 수준의 바인딩을 사용하여 모든 것이 올바르게 설정되었는지 확인하고 중복을 방지하고 싶습니다.
예를 들어 다음과 같은 모듈이 있다고 가정합니다.
public class ProductionModule implements Module {
public void configure(Binder binder) {
binder.bind(InterfaceA.class).to(ConcreteA.class);
binder.bind(InterfaceB.class).to(ConcreteB.class);
binder.bind(InterfaceC.class).to(ConcreteC.class);
}
}
또, 테스트에서는, 인터페이스 A와 인터페이스 B를 tact로 유지하면서, 인터페이스 C만을 오버라이드 하고 싶다고 생각하고 있습니다.따라서 다음과 같은 것을 원합니다.
Module testModule = new Module() {
public void configure(Binder binder) {
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(new ProductionModule(), testModule);
저도 다음 시도를 해봤지만, 잘 되지 않았습니다.
Module testModule = new ProductionModule() {
public void configure(Binder binder) {
super.configure(binder);
binder.bind(InterfaceC.class).to(MockC.class);
}
};
Guice.createInjector(testModule);
내가 원하는 것을 할 수 있는지, 아니면 내가 완전히 잘못 알고 있는지 아는 사람?
--- 후속 조치:인터페이스의 @ImplementedBy 태그를 사용하여 테스트 케이스에 바인딩을 제공하기만 하면 원하는 것을 달성할 수 있을 것 같습니다.이것은 인터페이스와 실장 사이에 1-1의 매핑이 있는 경우에 유효하게 동작합니다.
또한 이 문제에 대해 동료와 논의한 결과 모듈 전체를 덮어쓰고 모듈을 올바르게 정의해야 할 것으로 보입니다.이로 인해 바인딩이 모듈 내에서 잘못 배치되어 이동해야 하는 문제가 발생할 수 있습니다.따라서 바인딩을 덮어쓸 수 없게 되어 테스트 부하가 중단될 수 있습니다.
이것은 여러분이 찾고 있는 답이 아닐 수도 있지만, 만약 여러분이 단위 테스트를 쓰고 있다면, 여러분은 아마도 주입기를 사용하지 말고 손으로 모의 또는 가짜 물체를 주입해야 할 것입니다.
한편, 1개의 바인딩을 정말로 교환하고 싶은 경우는,Modules.override(..)
:
public class ProductionModule implements Module {
public void configure(Binder binder) {
binder.bind(InterfaceA.class).to(ConcreteA.class);
binder.bind(InterfaceB.class).to(ConcreteB.class);
binder.bind(InterfaceC.class).to(ConcreteC.class);
}
}
public class TestModule implements Module {
public void configure(Binder binder) {
binder.bind(InterfaceC.class).to(MockC.class);
}
}
Guice.createInjector(Modules.override(new ProductionModule()).with(new TestModule()));
자세한 것은 이쪽을 봐 주세요.
하지만 javadoc은Modules.overrides(..)
그럼 바인딩을 덮어쓸 필요가 없도록 모듈을 설계할 것을 권장합니다.이 예에서는, 다음의 바인딩을 이동함으로써, 이것을 실현할 수 있습니다.InterfaceC
다른 모듈로 이동합니다.
왜 상속을 사용하지 않는가?에서 특정 바인딩을 덮어쓸 수 있습니다.overrideMe
메서드, 공유 실장 유지configure
방법.
public class DevModule implements Module {
public void configure(Binder binder) {
binder.bind(InterfaceA.class).to(TestDevImplA.class);
overrideMe(binder);
}
protected void overrideMe(Binder binder){
binder.bind(InterfaceC.class).to(ConcreteC.class);
}
};
public class TestModule extends DevModule {
@Override
public void overrideMe(Binder binder) {
binder.bind(InterfaceC.class).to(MockC.class);
}
}
마지막으로 다음과 같이 인젝터를 만듭니다.
Guice.createInjector(new TestModule());
프로덕션 모듈을 변경하지 않고 다음과 같은 기본 메이브와 같은 프로젝트 구조를 사용하는 경우
src/test/java/...
src/main/java/...
새 클래스를 만들면 됩니다.ConcreteC
테스트 디렉토리에서 원래 클래스와 동일한 패키지를 사용합니다.는 기스를 .InterfaceC
로로 합니다.ConcreteC
다른 인터페이스는 모두 프로덕션 클래스에 바인딩됩니다.
각 테스트 클래스에 대한 사용자 지정 구성을 선언할 수 있는 Juckito를 사용하려고 합니다.
@RunWith(JukitoRunner.class)
class LogicTest {
public static class Module extends JukitoModule {
@Override
protected void configureTest() {
bind(InterfaceC.class).to(MockC.class);
}
}
@Inject
private InterfaceC logic;
@Test
public testLogicUsingMock() {
logic.foo();
}
}
다른 설정에서는 다른 모듈에 정의된 액티비티가 여러 개 있습니다.삽입되는 액티비티는 AndroidManifest.xml 파일에 자체 RoboGuice 모듈 정의와 함께 Android Library Module에 있습니다.
설정은 다음과 같습니다.라이브러리 모듈에는 다음과 같은 정의가 있습니다.
Android Manifest.xml:
<application android:allowBackup="true">
<activity android:name="com.example.SomeActivity/>
<meta-data
android:name="roboguice.modules"
android:value="com.example.MainModule" />
</application>
다음으로 주입되는 타입이 있습니다.
interface Foo { }
Foo의 디폴트 실장은 다음과 같습니다.
class FooThing implements Foo { }
Main Module은 Foo의 FooThing 구현을 설정합니다.
public class MainModule extends AbstractModule {
@Override
protected void configure() {
bind(Foo.class).to(FooThing.class);
}
}
마지막으로 Foo를 소비하는 액티비티:
public class SomeActivity extends RoboActivity {
@Inject
private Foo foo;
}
하고 있는 Android 에서는 「Android 어플리케이션 모듈」을 사용하고 하고 있습니다.SomeActivity
주사, 우리만의 시험용 주사, 우리만의 시험용 주사, 시험용 주사, 시험용 주사, 시험용 주사, 시험용 주사, 시험용 주사.Foo
.
public class SomeOtherActivity extends Activity {
@Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(this, SomeActivity.class);
startActivity(intent);
}
}
모듈 처리를 클라이언트애플리케이션에 공개해야 한다고 주장할 수도 있지만 Library Module은 SDK이기 때문에 삽입되는 컴포넌트를 대부분 숨길 필요가 있습니다.또한 조각 공개는 더 큰 의미를 가집니다.
(이것은 테스트용이므로 Some Activity의 내부 정보를 알고 있으며, (패키지 표시) Foo를 소비하고 있습니다).
이 방법은 타당합니다.테스트에 권장되는 덮어쓰기를 사용합니다.
public class SomeOtherActivity extends Activity {
private class OverrideModule
extends AbstractModule {
@Override
protected void configure() {
bind(Foo.class).to(OtherFooThing.class);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RoboGuice.overrideApplicationInjector(
getApplication(),
RoboGuice.newDefaultRoboModule(getApplication()),
Modules
.override(new MainModule())
.with(new OverrideModule()));
}
@Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(this, SomeActivity.class);
startActivity(intent);
}
}
그럼 ,, 그, 그, 그.SomeActivity
「」, 「」가 .OtherFooThing
그 주입을 위해서Foo
★★★★★★ 。
이 경우 테스트 상황을 기록하기 위해 OtherFooThing이 내부적으로 사용되었으며 FooThing은 기본적으로 다른 모든 용도로 사용되었습니다.
주의해 주세요.#newDefaultRoboModule
완벽하게 작동합니다.
언급URL : https://stackoverflow.com/questions/483087/overriding-binding-in-guice
'programing' 카테고리의 다른 글
Optional.orElse()와 Optional.OrseGet()의 차이점 (0) | 2022.07.04 |
---|---|
vue-cli3을 사용하여 플러그인 제거 (0) | 2022.07.04 |
Eslint 상태가 이미 선언된 [Vuex] (0) | 2022.07.04 |
Vue Jest 테스트에서 navigato.geolocation.getCurrentposition을 "mock"하는 방법 (0) | 2022.07.04 |
유형 스크립트가 포함된 Vue 플러그인이 null의 속성 '_init'을 읽을 수 없습니다. (0) | 2022.07.04 |