问题
I am working with Spring Framework
4.3.x and JUnit
4, I have the following structure
@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();
Thus the combination of:
@RunWith(Parameterized.class)
+SpringClassRule
+SpringMethodRule
works how is expected.
I have created a custom TestRule
through ExternalResource
as follows:
@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 {
...
}
Thus If I try then use:
@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();
The CompleteRule
is always ignored, it means the ExternalResource.before
method overridden
by CompleteRule
is never executed.
I have tried use
@Rule
public TestRule chain = RuleChain.outerRule(SPRING_CLASS_RULE)
.around(completeRule);
And does not work. Even worst is not possible add SpringMethodRule
because it implements MethodRule
and not TestRule
how the around
method asks for.
I want avoid use hierarchy
and work around with Rules
instead. It because is a best practice.
Thus: Is there an approach to work around this?
Note I found in other post how a suggestion create @Rule
and nest other Rules. Sadly no samples about this approach to test it.
Note is very important work around @RunWith(Parameterized.class)
because is mandatory use @Parameters(name="{index}: ''{0}''")
and SpringClassRule
and SpringMethodRule
are designed for this according with their API.
- SpringClassRule
- SpringMethodRule
回答1:
JUnit 4
The scenario you are describing is actually covered in SPR-15927.
It is impossible to have a custom TestRule
injected by Spring actually picked up as a rule by JUnit if Spring is also configured via rules (e.g., via SpringClassRule
and SpringMethodRule
).
The custom TestRule
field will in fact be injected by Spring, but that's too late in the game.
In other words, by the time the Spring rules are used to perform dependency injection, the current Runner
will not notice that the injected custom TestRule
exists, since the field was previously null
during the rule detection phase.
It's basically a "chicken and egg" problem, and there is no built-in workaround for JUnit 4.
However, you can achieve something similar by asking Spring to perform dependency injection on an existing rule, but that requires custom code. See SPR-10252 for details.
JUnit Jupiter (JUnit 5)
With JUnit Jupiter 5.1 this should actually be easier to accomplish. Namely, you can combine parameterized test support with Spring without any problems.
The trick with JUnit Jupiter is to make sure you register the SpringExtension
at the class level (e.g., via @ExtendWith
, @SpringJUnitConfig
, or similar). Then you can use @RegisterExtension
and @Autowired
on a field to have a Spring-managed extension injected into the test instance and used by JUnit Jupiter.
来源:https://stackoverflow.com/questions/49238290/how-configure-correctly-runwithparameterized-class-springclassrule-spring