我理解依赖注入,但我真正不理解的是,依赖注入的用途是什么。
正如提到here这有助于轻松测试代码(它是一种非常有用的测试技术,因为它允许依赖项被模拟或删除。) ,但现在有很多模仿框架,如Mockito,powermockito,这些工作可以比依赖注入更好地完成这些工作吗?
如果有人能用代码解释,那就太棒了。
提前致谢。
答案 0 :(得分:7)
Dependency injection
不能替代mocking frameworks
。这是一个要求。如果您有很多依赖项,那么模拟依赖项并因此测试代码会更加困难。
DI
还允许您拥有更松散耦合的代码。类可以简单地通过注入它们来使用其他类,而不是知道如何构造(或获取特定类)的实例。
答案 1 :(得分:7)
DI作为一种技术的主要用途是:
它导致代码更容易测试(使用Mocking)。这意味着为了使用模拟框架(Mockito等),你应该使用更多的DI。如果您不使用DI并编写直接实例化对象的代码 - 那么实际上您不能使用Mockito来模拟您的依赖项。
让我们说你编写代码来演奏管弦乐队。你的主要课程取决于许多其他课程(也许其他人写的)。
让我们说你写了这个:
public class Orchestra {
private Drums drum;
private Violin violin;
private Guitar guitar;
public Orchestra() {
drum = new Drum();
violin = new Violin();
guitar = new Guitar();
}
public Music play(){
// use above in some way to run your orchestra
// start with violin
// add some guitar and then bring in the drums too
}
}
现在您要确保play
中的逻辑准确无误。当你上课时,你会发现音乐不是你所期望的。 (也许鼓声正在开始时开始)。您想测试代码play
的逻辑。你会怎么做到这里?您无法控制依赖项。您不知道Drum
中的play()
代码或您自己的逻辑是否存在问题。
你想在这里嘲笑 Drum
。但你不能轻易做到这一点。因为您的代码不使用DI。它直接在里面实例化Drum
。
现在让我们使用DI,看看它有何帮助。
public class Orchestra {
private Drums drum;
private Violin violin;
private Guitar guitar;
public Orchestra(Drums d,Violin v, Guitar g ) {
drum = d;
violin = v;
guitar = g;
}
public Music play(){
// use above in some way to run your orchestra
}
}
使用此代码,您可以轻松地在测试中模拟Drum
。
class TestOrchestra {
public void testPlay(){
Drum mockDrum = mock(Drum.class);
Violin mockViolin = mock(Violin.class);
Guitar mockGuitar = mock(Guitar.class);
// add mock behaviour to above , here you control precisely what these dependencies will do inside your code
Orchestra orch = new Orchestra(mockDrum, mockViolin,mockGuitar);
// now play and test your logic
}
}
使用DI的第二个好处是,它有助于改变程序较大部分的实现,而无需完成整个代码。
再次 - 参考上文,假设您一直在使用特定类型的吉他演奏您的管弦乐队(由您的代码在内部实例化)。
现在你要换成一个全新的电吉他。没有DI,你必须打开你的Orchestra
课程,检查你创建Guitar
的位置并更改那行代码。您必须确保代码的其他部分不会无意中更改并测试整个Orchestra
以确保正常工作。
使用DI,你可以避免这一切。您只需将新的Guitar
对象注入构造函数中。而已。因为您已经自己测试了新的Guitar
对象(并且它符合interface Guitar
的合同 - 您可以放心,通过注入这个新吉他,您的Orchestra
代码不会被破坏这对改善你的管弦乐队来说要好得多。