繁体   English   中英

当存在来自超类的依赖注入时,如何设置测试?

[英]How do I set up testing when there is a dependency injection from super class?

我的代码是这样设置的。

abstract class BaseController {
   @Inject Store store; 
}

class MyController extends BaseController {
   private final Validator validator;

   @Inject
   public MyController(Validator validator) {
      this.validator = validator;
   }

   public boolean someMethod() {
      a = store.storingMethod();
      b = validator.validate(a);
      ...
      ...
      return true;
   }
}

现在我想为myController编写测试。 在测试中,我想使用注入的Store但我想模拟Validator 我试过这样的事情。

@RunWith(MockitoJUnitRunner.class)
public class MyControllerTest() {
   private MyController myController;
   @Mock private Validator validator;

   @Before
   public void before() {
      myController = new MyController(validator);
   }
}

我知道,如果我将Store storeBaseControllerMyController ,我可以在构造函数中初始化它(就像我对验证器所做的那样)。 但是,我希望在 Base 类中有 Store,因为它会被其他扩展它的类使用。

根据我的课程设置方式,如何在测试时注入Store

不要使用字段注入。 使用构造函数注入。

abstract class BaseController {
    final Store store; 

    BaseController(Store store) {
        this.store = store;
    }
}

class MyController extends BaseController {
   private final Validator validator;

   @Inject
   public MyController(Validator validator, Store store) {
      super(store);
      this.validator = validator;
   }
}

关于这个主题有一些争论,但是您的示例清楚地说明了使用字段注入使类更难测试的情况。

Spring @Autowire 关于属性 vs 构造函数

依赖注入:字段注入 vs 构造函数注入?

还值得注意的是

Spring团队普遍提倡构造函数注入

来源

我通常使用以下模式解决这个问题:

abstract class BaseController {
    private final Store store; 

    protected BaseController (Store store) {
        this.store = store;
    }

    protected Store getStore() {
        return this.store;
    }
}

class MyController extends BaseController {
    private final Validator validator;

    @Inject
    public MyController(Store store, Validator validator) {
       super(store);
       this.validator = validator;
    }

    public boolean someMethod() {
        a = getStore().storingMethod();
        b = validator.validate(a);
        ...
        ...
        return true;
    }
}

因此,无论任何可用的注入框架如何,都可以使用基类。

您可以使用ReflectionTestUtils来设置您的字段值。

在你的pom.xml 中导入它:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.2.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.2.RELEASE</version>
    <scope>test</scope>
</dependency>

使用它来设置您的商店:

@RunWith(MockitoJUnitRunner.class)
public class MyControllerTest() {
   private MyController myController;
   @Mock private Validator validator;

   @Before
   public void before() {
      myController = new MyController(validator);
      ReflectionTestUtils.setField(myController, "store", new YourTestStore());

      // more testing
   }
}

更多信息@ https://www.baeldung.com/spring-reflection-test-utils

另外,请注意,我认为这不是最佳实践。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM