有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我的代码是这样设置的

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 storeBaseController移动到MyController,我可以在构造函数中初始化它(就像我对验证器所做的那样)。但是,我希望将存储放在基类中,因为它将被扩展它的其他类使用

按照我的类设置方式,在测试时如何注入Store


共 (3) 个答案

  1. # 1 楼答案

    可以使用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

    另外,请注意,我不认为这是最佳做法

  2. # 2 楼答案

    不要使用现场注射。使用构造函数注入

    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 on Properties vs Constructor

    Dependency Injection: Field Injection vs Constructor Injection?

    同样值得注意的是

    The Spring team generally advocates constructor injection

    Source

  3. # 3 楼答案

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

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

    因此,基类可以在任何可用的注入框架中使用