首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用自定义@规则正确配置@RunWith(Parameterized.class) + SpringClassRule + SpringMethodRule?

如何使用自定义@规则正确配置@RunWith(Parameterized.class) + SpringClassRule + SpringMethodRule?
EN

Stack Overflow用户
提问于 2018-03-12 14:58:15
回答 1查看 1.3K关注 0票数 2

我正在使用Spring Framework 4.3.x和JUnit 4,我有以下结构

代码语言:javascript
复制
@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,如下所示:

代码语言:javascript
复制
@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 {
      ...
    }

因此,如果我尝试使用:

代码语言:javascript
复制
@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总是被忽略,这意味着被CompleteRule覆盖的ExternalResource.before方法永远不会被执行。

我试过用

代码语言:javascript
复制
@Rule
public TestRule chain = RuleChain.outerRule(SPRING_CLASS_RULE)
                                                .around(completeRule);

也不起作用。即使是最糟糕的情况也不可能添加SpringMethodRule,因为它实现了MethodRule而不是TestRule,这是around方法所要求的。

我希望避免使用hierarchy,转而使用Rules。因为这是最好的做法。

因此:是否有办法解决这一问题?

Note我在其他文章中发现了一个建议是如何创建@Rule和嵌套其他规则的。遗憾的是,没有关于这种方法的样本来测试它。

Note是围绕@RunWith(Parameterized.class)进行的非常重要的工作,因为是强制性的使用,@Parameters(name="{index}: ''{0}''")SpringClassRuleSpringMethodRule都是为此而设计的,符合它们的API。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-12 15:12:44

JUnit 4

您所描述的场景实际上是在https://jira.spring.io/browse/SPR-15927中描述的。

如果Spring也通过规则(例如,通过TestRuleSpringMethodRule)进行配置,那么在Spring之前注入自定义的JUnit是不可能的。

实际上,自定义的TestRule字段将在Spring之前被注入,但在游戏中已经太晚了。

换句话说,当使用Spring规则执行依赖项注入时,当前Runner将不会注意到注入的自定义TestRule存在,因为在规则检测阶段该字段以前是null

这基本上是一个“鸡与蛋”的问题,而且JUnit 4没有内置的解决方法。

但是,您可以通过要求Spring对现有规则执行依赖注入来实现类似的目标,但这需要自定义代码。详情请参见SPR-10252

JUnit木星(JUnit 5)

使用JUnit木星5.1,这实际上应该更容易实现。也就是说,您可以将参数化测试支持与Spring结合在一起,而不会出现任何问题。

JUnit木星的诀窍是确保您在类级别注册SpringExtension (例如,通过@ExtendWith@SpringJUnitConfig或类似的)。然后,您可以在字段中使用@RegisterExtension@Autowired,将Spring管理的扩展注入到测试实例中,并由JUnit木星使用。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49238290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档