依赖注入如何允许更容易的测试 - 需要一个java示例来掌握这个概念?

时间:2014-05-12 20:44:22

标签: java junit

所以我理解什么是依赖注射:

  

而不是让您的对象创建依赖项或询问   factory对象为它们制作一个,你传递所需的依赖项   在构造函数中或通过属性setter,你做到了   别人的问题(依赖图中的一个对象,或者   构建依赖图的依赖注入器。依赖   据我所知,这是当前对象需要的任何其他对象   持有

的参考

大。现在,这如何使测试变得更容易?它是有意义的,但我想要一个能够巩固我脑海中这个概念的例子。您是否可以提供一个测试代码变得比在类中硬连接依赖项时更容易的示例?

提前谢谢。

2 个答案:

答案 0 :(得分:6)

我们举一个例子。假设您要测试雷管:

public class Detonator {
    private Bomb bomb = new AtomicBomb();

    public void pushButton() {
        // do some stuff to test, and at the end
        bomb.explode();
    }
}

现在,你遇到了一个严重的问题,因为每次你想测试雷管时,都会让炸弹爆炸,这是非常昂贵的。所以你使用依赖注入来解决问题:

public class Detonator {
    private Bomb bomb;

    public Detonator(Bomb bomb) {
        this.bomb = bomb;
    }

    public void pushButton() {
        // do some stuff to test, and at the end
        bomb.explode();
    }
}

您的测试会有什么变化?一切,因为现在你可以这样测试雷管:

Bomb fakeBomb = new WaterBalloonBomb();
Detonator detonator = new Detonator(fakeBomb);
detonator.pushButton();
// test that the fake bomb has exploded

现在这是一个非常不切实际的场景。但是只需用BankingService代替Detonator,用MainFrameDatabaseAccessor代替Bomb,你就会明白:需要一个填充的大型机数据库来测试服务的业务逻辑非常麻烦,使得测试很难编写,执行起来也很慢。通过使用模拟框架,您可以创建注入类的动态实现,并验证此模拟对象的断言:

MainframeDatabaseAccessor mock = mock(MainFrameDatabaseAccessor.class);
when(mock.findAccount(id1)).thenReturn(sourceAccount);
when(mock.findAccount(id2)).thenReturn(destinationAccount);

BankingService service = new BankingService(mock);
service.transfer(id1, id2, 1000);
// now test that sourceAccount has lost 1000 dollars and destinationAccount has won 1000 dollars

verify(mock).logTransaction(any(Transaction.class));

答案 1 :(得分:0)

定期批处理过程将新事实写入数据库并对NOW-7 DAYS进行检查。如果你准备测试数据,那“现在”是痛苦的。在类外面初始化是一个选项:数据库连接会使DI更加常规。

class UpdateBatch { // Class to test
    Date now; // Java 7
    Instant now; // Java 8

    Connection connection;
}

在没有DI的情况下可以做到:

class ProductionUpdateBatch extends UüdateBatch { // No  longer tested
    ...
    now = new Date();
    now = Instant.now();
    connection = ...
}

但是使用DI,可以在XML源代码中保持实际值声明。 特别是您可以在应用程序之外的应用程序容器中定义它。

对于更抽象的概念视角,您可能会研究控制反转