简体   繁体   English

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

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

My code is setup like this.我的代码是这样设置的。

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;
   }
}

Now I wanted to write tests for myController .现在我想为myController编写测试。 In the test, I want to use the injected Store but I want to mock out the Validator .在测试中,我想使用注入的Store但我想模拟Validator I tried something like this.我试过这样的事情。

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

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

I know, if I move the Store store from the BaseController to MyController , I can initialize it in the constructor (just like I did for the validator).我知道,如果我将Store storeBaseControllerMyController ,我可以在构造函数中初始化它(就像我对验证器所做的那样)。 But, I want to have the Store in the Base class as it will be used by other classes extending it.但是,我希望在 Base 类中有 Store,因为它会被其他扩展它的类使用。

With the way my classes are set up, How do I inject the Store while testing?根据我的课程设置方式,如何在测试时注入Store

Don't use field injection.不要使用字段注入。 Use constructor injection.使用构造函数注入。

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;
   }
}

There is a bit of debate on the subject, but your example is a clear example of a situation in which the use of field injection makes a class much harder to test.关于这个主题有一些争论,但是您的示例清楚地说明了使用字段注入使类更难测试的情况。

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

Dependency Injection: Field Injection vs Constructor Injection? 依赖注入:字段注入 vs 构造函数注入?

It is also worth noting that还值得注意的是

The Spring team generally advocates constructor injection Spring团队普遍提倡构造函数注入

Source 来源

I usually solve this using the following pattern:我通常使用以下模式解决这个问题:

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;
    }
}

So the base class can be used regardless of any injection framework available.因此,无论任何可用的注入框架如何,都可以使用基类。

You can use ReflectionTestUtils to set your field value.您可以使用ReflectionTestUtils来设置您的字段值。

Import it in your pom.xml :在你的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>

Use it to set your store:使用它来设置您的商店:

@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
   }
}

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

Also, note that I do not think this is best practice.另外,请注意,我认为这不是最佳实践。

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

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