@Robinの戦略パターンの提案をより具体的にするために:(元の質問の公開APIは変更されていないことに注意してください。)
public class MyLegacyClass {
private static Strategy strategy = new JNDIStrategy();
public static SomeLegacyClass doSomeLegacyStuff(SomeOtherLegacyClass legacyObj) {
// legacy logic
SomeLegacyClass result = strategy.doSomeStuff(legacyObj);
// more legacy logic
return result;
}
static void setStrategy(Strategy strategy){
MyLegacyClass.strategy = strategy;
}
}
interface Strategy{
public SomeLegacyClass doSomeStuff(SomeOtherLegacyClass legacyObj);
}
class JNDIStrategy implements Strategy {
private static final String jndiName = "java:comp/env/jdbc/LegacyDataSource";
public SomeLegacyClass doSomeStuff(SomeOtherLegacyClass legacyObj) {
// do stuff using jndiName
}
}
...そして JUnit テスト。私は、このセットアップ/ティアダウン メンテナンスを行わなければならないのはあまり好きではありませんが、静的メソッド (またはシングルトン) に基づく API を使用することの残念な副作用です。このテストで私が気に入っているのは、JNDI を使用しないことです。(a) 高速に実行され、(b) 単体テストは doSomeLegacyStuff() メソッドのビジネス ロジックのみをテストする必要があり、実際のデータ ソース。(ちなみに、これはテスト クラスが MyLegacyClass と同じパッケージにあることを前提としています。)
public class MyLegacyClassTest extends TestCase {
private MockStrategy mockStrategy = new MockStrategy();
protected void setUp() throws Exception {
MyLegacyClass.setStrategy(mockStrategy);
}
protected void tearDown() throws Exception {
// TODO, reset original strategy on MyLegacyClass...
}
public void testDoSomeLegacyStuff() {
MyLegacyClass.doSomeLegacyStuff(..);
assertTrue(..);
}
static class MockStrategy implements Strategy{
public SomeLegacyClass doSomeStuff(SomeOtherLegacyClass legacyObj) {
// mock behavior however you want, record state however
// you'd like for test asserts. Good frameworks like Mockito exist
// to help create mocks
}
}
}