Java - 仅在没有字段@Autowired

时间:2018-04-11 13:25:42

标签: java unit-testing dependency-injection superclass jsr330

我正在处理设计情况,我不知道如何解决它,或者我的微观设计是否有任何问题。

public abstract class A implements SomeFrameworkInterface {

  private final Param1 a1;

  @Inject
  private Param2 a2;

  protected A(Param1 a1) {
    this.a1 = a1;
  }

  @Override
  public someFrameworkInterfaceMethod() {
    //code
    doMyStuff();
  }

  protected abstract void doMyStuff();
} 

@Named
@SomeCustomAnnotation(property="someProperty")
public class B extends A {

  @Inject
  public B(Param1 b1) { //b1 is different for every implementation of class A, through some annotations
    super(b1);
  }

  @Override
  protected void doMyStuff() {
    //code
  }

}
  • 我需要从A类改变“@Inject Param2 a2”进行注入 通过构造函数,所以代码是可测试的,我会 清除与此相关的代码气味。
  • 我不想从B构造函数发送它,因为我会 在B构造函数中添加一个参数,在A构造函数和 对于A ...的所有实现中的每个构造函数,但是 子类从不需要知道Param2实例。
  • Param2可能是静态的,但需要注入,因为它是 组件(@Named),所以我没有找到静态注入的方法。

限制如下:

  1. 第三方框架,包含要使用的自定义注释和界面 待实施
  2. 代码必须是可测试的,因此不允许@Inject / @在字段上自动连接
  3. 我们被限制使用“封装”的Spring 提到的自定义框架,所以我们只能使用纯Java(JSR-330)。 (如果在Spring中有任何解决方案,也很高兴了解它)

2 个答案:

答案 0 :(得分:0)

在不经过B的情况下,不可能将任何参数传递给A的构造函数,因为实际上是在构造B的实例。只有委托构造函数才能构造B实例的“A部分”。

你能做的最多就是将某种“无类型”参数传递给B的构造函数,这样至少B不会知道Param2,但这种治疗方法听起来已经比疾病更糟糕了写下来......

我没有看到在构建后注入Param2使代码变得不那么可测试。 OTOH,使用静态场肯定会这样做。

答案 1 :(得分:0)

我找到了测试它的解决方案,但它看起来有点奇怪。我的意思是我不明白为什么或如何发生这种情况,但它以干净的方式完成工作。 测试类看起来像:

@RunWith(MockitoJUnitRunner.class)
public BTest {

  @Mock
  private Param1 mockParam1;

  @Mock
  private Param2 mockParam2;

  @InjectedMocks
  private A b = new B(null);

  @Test
  public someFrameworkInterfaceMethodTest() {
    when(...).thenReturn(...)
    b.someFrameworkInterfaceMethod();
    verify(...).someCall(any());
  }

}

我很难弄明白为什么 Param1 a1 仍然为空,并试图找出不同的解决方案。但似乎Mockito在构造后再次注入字段(在调用“new B(null)”之后 - 如果字段为null或不确定)。 Param2 a2 被mockito嘲笑,而 Param1 a1 仍然为空,这是因为 Param1 a1上的“最终”关键字 in B class