问题描述
我有以下遗留代码:
public class MyLegacyClass
{
private static final String jndiName = "java:comp/env/jdbc/LegacyDataSource"
public static SomeLegacyClass doSomeLegacyStuff(SomeOtherLegacyClass legacyObj)
{
// do stuff using jndiName
}
}
此类在 J2EE 容器中工作.
This class is working in a J2EE-Container.
现在我想在容器外测试类.
Now I would like to test the class outside of the container.
最好的策略是什么?重构基本上是允许的.
What is the best strategy?Refactoring is basically allowed.
允许访问 LegacyDataSource(测试不必是纯"单元测试).
Accessing the LegacyDataSource is allowed (the test does not have to be a "pure" unit-test).
不允许引入额外的运行时框架.
Introducing additional runtime-frameworks is not allowed.
推荐答案
只是为了使@Robin 对策略模式的建议更加具体:(请注意,您原始问题的公共 API 保持不变.)
Just to make @Robin's suggestion of a strategy pattern more concrete: (Notice that the public API of your original question remains unchanged.)
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 在同一个包中.)
...and JUnit test. I'm not a big fan of having to do this setup/teardown maintenance, but that's an unfortunate side effect of having an API based on static methods (or Singletons for that matter). What I do like about this test is it does not use JNDI - that's good because (a) it'll run fast, and (b) the unit test should only be testing the business logic in doSomeLegacyStuff() method anyway, not testing the actual data source. (By the way, this assumes the test class is in the same package as 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
}
}
}
这篇关于重构静态方法/静态字段以进行测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!