What is the life cycle of an Extension instance trying to write an Extension for JUnit 5 (JUnit Jupiter)? Since it became, it is a memorandum.
TL;TR
--The instance registered with @Extension
is shared for each test class, and if the test class is different, the Extension instance will be different.
--Instance registered with @RegisterExtension
--In the case of static field, it is shared for each test class.
--For non-static fields, it depends on the life cycle of the test class.
The JUnit 5 Extension Model is a mechanism for standardizing pre-processing, post-processing, exception handling, etc. for each test. Compared to Junit 4's Rule
etc., the degree of freedom is lower, but you can easily create an extension just by implementing an interface corresponding to the extension point.
There are three ways to use Extension.
@Extension
.@RegisterExtension
.This time, use methods 1 and 2 to check when the Extension instance is created.
FooExtension.java
import org.junit.jupiter.api.extension.*;
public class FooExtension implements BeforeEachCallback, AfterEachCallback, BeforeAllCallback, AfterAllCallback {
{
System.out.println(String.format("[%s] created", this.toString()));
}
@Override
public void beforeAll(ExtensionContext extensionContext) throws Exception {
System.out.println(String.format("[%s] before all", this.toString()));
}
@Override
public void beforeEach(ExtensionContext context) throws Exception {
System.out.println(String.format("[%s] before each", this.toString()));
}
@Override
public void afterEach(ExtensionContext extensionContext) throws Exception {
System.out.println(String.format("[%s] after each", this.toString()));
}
@Override
public void afterAll(ExtensionContext extensionContext) throws Exception {
System.out.println(String.format("[%s] after all", this.toString()));
}
}
@Extension
@ExtendWith(FooExtension.class)
public class ExtensionTest {
@Test
void test1() { System.out.println("test 1"); }
@Test
void test2() { System.out.println("test 2"); }
@Test
void test3() { System.out.println("test 3"); }
}
[example.FooExtension@70325e14] created
[example.FooExtension@70325e14] before all
[example.FooExtension@70325e14] before each
test 1
[example.FooExtension@70325e14] after each
[example.FooExtension@70325e14] before each
test 2
[example.FooExtension@70325e14] after each
[example.FooExtension@70325e14] before each
test 3
[example.FooExtension@70325e14] after each
[example.FooExtension@70325e14] after all
You can see that each test shares one Extension instance.
An instance of ExtensionTest is created for each test, but the same result was obtained when changing to share the instance of ExtensionTest with @TestInstance (Lifecycle.PER_CLASS)
.
@RegisterExtension
+ Register Extension with static fieldSecondExtensionTest.java
public class SecondExtensionTest {
@RegisterExtension
static FooExtension fooExtension = new FooExtension();
@Test
void test1() { System.out.println("test 1"); }
@Test
void test2() { System.out.println("test 2"); }
@Test
void test3() { System.out.println("test 3"); }
}
[example.FooExtension@55183b20] created
[example.FooExtension@55183b20] before all
[example.FooExtension@55183b20] before each
test 1
[example.FooExtension@55183b20] after each
[example.FooExtension@55183b20] before each
test 2
[example.FooExtension@55183b20] after each
[example.FooExtension@55183b20] before each
test 3
[example.FooExtension@55183b20] after each
[example.FooExtension@55183b20] after all
Of course, since it is a static field, the same instance is shared.
@RegisterExtension
+ Register Extension in non-static fieldLet's remove the static
of the fooExtension
of the SecondExtensionTest earlier.
Lifecycle.PER_METHOD
SecondExtensionTest.java
public class SecondExtensionTest {
@RegisterExtension
- static FooExtension fooExtension = new FooExtension();
+ FooExtension fooExtension = new FooExtension();
//Omission
}
[example.FooExtension@40a4337a] created
[example.FooExtension@40a4337a] before each
test 1
[example.FooExtension@40a4337a] after each
[example.FooExtension@fa4c865] created
[example.FooExtension@fa4c865] before each
test 2
[example.FooExtension@fa4c865] after each
[example.FooExtension@3bd82cf5] created
[example.FooExtension@3bd82cf5] before each
test 3
[example.FooExtension@3bd82cf5] after each
You can see that each test has a different instance of Extension. This is because an instance of SecondExtensionTest itself is created for each test.
In addition, BeforeAll and AfterAll are not working, but in the case of Lifecycle.PER_METHOD
as well as when adding @BeforeAll
to the method, it must be static.
Lifecycle.PER_CLASS
So, let's make the life cycle of Second Extension Test a form in which an instance is created only once.
SecondExtensionTest.java
+ @TestInstance(Lifecycle.PER_CLASS)
public class SecondExtensionTest {
@RegisterExtension
FooExtension fooExtension = new FooExtension();
//Omission
}
[example.FooExtension@c730b35] created
[example.FooExtension@c730b35] before all
[example.FooExtension@c730b35] before each
test 1
[example.FooExtension@c730b35] after each
[example.FooExtension@c730b35] before each
test 2
[example.FooExtension@c730b35] after each
[example.FooExtension@c730b35] before each
test 3
[example.FooExtension@c730b35] after each
[example.FooExtension@c730b35] after all
Extension instance is shared. Also, Before All and After All are now working. If you register an extension in a non-static field in this way, it naturally depends on the life cycle of the original test class.
https://junit.org/junit5/docs/current/user-guide/#extensions
Recommended Posts