只是为了让一个@策略模式更具体的罗宾的建议:(请注意,你原来的问题的公共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测试。我不喜欢做这种设置/拆卸维护,但这是一个基于静态方法(或Singletons)的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
}
}
}
我根据你的新限制更新了我的答案。我们实际上有一个系统必须解决同样的问题。 – Robin 2008-10-30 13:41:23