当超类有依赖注入时,如何设置测试?



我的代码是这样设置的。

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 放在基类中,因为它将被其他扩展它的类使用。

根据我的类设置方式,如何在测试时注入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;
}
}

关于这个主题有一些争论,但你的例子是一个明显的例子,说明使用场注入使类更难测试的情况。

关于属性与构造函数的春季@Autowire

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

还值得注意的是,

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

的更多信息另外,请注意,我认为这不是最佳做法。

最新更新