java – 测试和继承问题

想象一下,你有一个应用程序,你想对它进行单元测试和功能测试(不是很难想象).你可能有一个抽象类,我们称之为AbstractTestClass,你的所有单元测试都会从中扩展.

AbstractTestClass看起来像这样(使用JUnit 4):

class AbstractTestClass {
    boolean setupDone = false;

    @Before
    public void before() {
        if(!setupDone) {
            // insert data in db
            setupDone = true;
        }
    }
}

这就是我正在努力的方向.我有另一个测试Web界面的抽象类:

class AbstractWebTestClass extends WebTestCase {
    boolean setupDone = false;

    @Before
    public void before() {
        if(!setupDone) {
            // here, make a call to AbstractTestClass.before()
            // init the interfaces
            setupDone = true;
        }
        // do some more thing
    }
}

它几乎是同一个类,除了它扩展到WebTestCase.这个设计可以让我在单元测试时获得与测试接口时相同的数据.

通常,在处理此类问题时,您应该优先考虑组合而不是继承或使用策略模式.

不幸的是,我不喜欢在这个特定场景中支持组合而非继承的想法,我不知道如何使用策略模式,可能存在设计缺陷,我无法完全看到解决方案.

我怎样才能设计这个架构以实现我的目标.

最佳答案 我将通过以下方式实现此目的:

class Example {

class LazyInitStrategy implements Runnable {
    private final Runnable operation;
    private boolean done = false;

    LazyInitStrategy(Runnable operation) {
        this.operation = operation;
    }

    @Override
    public void run() {
        if (!done) {
            operation.run();
            done = true;
        }
    }
}

private final class AbstractInit implements Runnable {
    public void run() {
        // insert data in db
    }
}

private final class AbstractWebInit implements Runnable {
    public void run() {
        // here, make a call to AbstractTestClass.before() init the interfaces
    }
}

class AbstractTestClass {

    final LazyInitStrategy setup = new LazyInitStrategy(new AbstractInit());

    @Before
    public void before() {
        setup.run();
        // do some more thing
    }
}

class AbstractWebTestClass extends WebTestCase {

    final LazyInitStrategy setupInfo = new LazyInitStrategy(new AbstractWebInit());

    @Before
    public void before() {
        setupInfo.run();
        // do some more thing
    }
}

}

当然这是一个非常简单的解决方案,但它应该消除if / else逻辑重复,以检查设置是否已完成.使用Runnable是可选的,我这样做只是为了演示目的,在阅读世界中你可能会使用另一个界面.

点赞