我正在使用Spring Framework
4.3.x和JUnit
4,我有以下结构
@Transactional
@WebAppConfiguration
@RunWith(Parameterized.class)
@ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})
@TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class CompleteTest {
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
因此组合:
@RunWith(Parameterized.class)
+ SpringClassRule
+ SpringMethodRule
如何预期。
我已通过TestRule
创建了自定义ExternalResource
,如下所示:
@Component
public class CompleteRule extends ExternalResource {
private static final Logger logger = LoggerFactory.getLogger(CompleteRule.class.getSimpleName());
private final WebApplicationContext webApplicationContext;
private final Environment environment;
private MockMvc mockMvc;
public CompleteRule(WebApplicationContext webApplicationContext, Environment environment) {
this.webApplicationContext = webApplicationContext;
this.environment = environment;
}
@Override
protected void before() throws Throwable {
...
}
因此,如果我尝试,请使用:
@Transactional
@WebAppConfiguration
@RunWith(Parameterized.class)
@ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})
@TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class CompleteTest {
private static final Logger logger = LoggerFactory.getLogger(CompleteTest.class.getSimpleName());
@Rule
@Autowired
public CompleteRule completeRule;
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
CompleteRule
始终被忽略,这意味着覆盖了ExternalResource.before
方法
CompleteRule
永远不会被执行。
我尝试过使用
@Rule
public TestRule chain = RuleChain.outerRule(SPRING_CLASS_RULE)
.around(completeRule);
并不起作用。即使是最糟糕的情况也无法添加SpringMethodRule
,因为它会实现MethodRule
而不是TestRule
around
方法要求的方式。
我希望避免使用hierarchy
并改为使用Rules
。这是因为这是一种最佳实践。
因此:有解决方法吗?
注意我在其他帖子中发现了一条建议如何创建@Rule
并嵌套其他规则。遗憾的是没有关于这种测试方法的样本。
注意是非常重要的@RunWith(Parameterized.class)
工作,因为必须使用@Parameters(name="{index}: ''{0}''")
SpringClassRule
和SpringMethodRule
是根据其API设计的。
答案 0 :(得分:5)
您所描述的方案实际上涵盖在SPR-15927。
中如果通过规则(例如,通过TestRule
和Spring配置Spring,那么由Spring注入的自定义SpringClassRule
实际上被JUnit选为规则是不可能的。 SpringMethodRule
)。
自定义TestRule
字段实际上将由Spring注入,但这在游戏中为时已晚。
换句话说,当Spring规则用于执行依赖注入时,当前Runner
将不会注意到注入的自定义TestRule
存在,因为该字段之前是{{1}在规则检测阶段。
这基本上是一个“鸡蛋和鸡蛋”问题,而且JUnit 4没有内置的解决方法。
但是,您可以通过要求 Spring对现有规则执行依赖注入来实现类似的操作,但这需要自定义代码。有关详细信息,请参阅SPR-10252。
使用JUnit Jupiter 5.1实际上应该更容易实现。也就是说,您可以将参数化测试支持与Spring结合起来,没有任何问题。
使用JUnit Jupiter的技巧是确保在类级别注册null
(例如,通过SpringExtension
,@ExtendWith
或类似名称)。然后,您可以在字段上使用@SpringJUnitConfig
和@RegisterExtension
将Spring管理的扩展注入到JUnit Jupiter使用的测试实例和中。