依赖注入的Spring最佳实践

时间:2016-07-01 02:35:21

标签: spring unit-testing dependency-injection mocking mockito

我对春天的DI感到困惑

public interface C{
    void methodC();
}

public class CAutowired implements C{
    @Autowired
    private A a;
    @Autowired
    private B b;

    public void methodC(){
       a.methodA();
       b.methodB();
    }
}

我有两个接口A和B,2个类实现它。 所以,我有2个实现接口C的类,它依赖于接口A和B

这是案例1:

  <beans>
       <bean id="classA" class="com.example.AImpl" />
       <bean id="classB" class="com.example.BImpl" />
       <bean id="classC" class="com.example.CAutowired" />
    <beans>

档案.xml配置

public class CInitInject implements C{
    private A a;
    private B b;

    public CInitInject(A a, B b){
       this.a = a;
       this.b = b;
    }

    public void methodC(){
       a.methodA();
       b.methodB();
    }
}

在这种情况下,我有一个问题:    - 当我为类CATowowired编写unitTest时如何模拟A和B

这是案例2:

  <beans>
       <bean id="classA" class="com.example.AImpl" />
       <bean id="classB" class="com.example.BImpl" />
       <bean id="classC" class="com.example.CInitInject">
             <constructor-arg ref="classA" />
             <constructor-arg ref="classB" />
       </bean>
    <beans>

档案.xml配置

@Mock
private A aMock;
@Mock
private B bMock;

private C c;

public void setUp(){
   c = new CInitInject(aMock, bMock);
}

@Test
public void test(){
   // todo Test somemethod
}

在这种情况下,我在.NET中获得相同的DI方法。我可以注射模拟A和B. 进入构造函数。例如:

{{1}}

最后,我有一个问题

  1. 案例1和案例2之间的最佳做法是什么?
  2. 如何在单元测试时进行模拟

1 个答案:

答案 0 :(得分:0)

<强>(1)

现在习惯将bean注入构造函数。

它被认为是最佳实践,因为它严格通知类的用户(在本例中为CInitInject的用户)对此类的期望是什么,以使其正常工作。用户不必猜测setter会发生哪些依赖项。

<强>(1.1)

“案例1”的代码示例捆绑了两种代码样式,您可能希望避免这种情况。

在注释驱动编码和XML之间选择是很常见的。

对于这种情况,如果您选择使用注释,您的代码将看起来像这样(注意不涉及XML):

public interface C{
    void methodC();
}

@Bean(name="a")
public class AImpl implements A{
    public void methodA(){
        // todo something
    }
}

@Bean
public class CAutowired implements C{
    @Autowired
    private A a;
    @Autowired
    private B b;

    public void methodC(){
       a.methodA();
       b.methodB();
    }
}

请参阅example了解如何使用帮助代码来完成这项工作。

<强>(1.2)

如果你选择使用注释驱动的编码,这里是一个将bean注入构造函数的例子:

@Bean
public class CAutowired implements C {
    private A a;
    private B b;

    @Autowired
    public CAutowired(A a, B b) {
        this.a = a;
        this.b = b;
    }
}

<强>(1.3)

在使用注释时,避免将Spring硬连接到系统中也很常见。因此,有些人创建的类可以识别spring和其他类(例如CAutowired,现在将重命名为CImpl),只有他们使用@Autowired@Bean注释。 例如:

//just an example, you'll think of how this works for YOU
public class OneOfSomeSpringManagers {
    public OneOfSomeSpringManagers() {
        C c = getC(getA());
    }

    @Bean
    public A getA() {
        ...
    }

    ...
}

<强>(2)

在单元测试中使用Mockito to mock the injected dependencies