I am the very beginner of Java, Spring and JUnit. I am trying to write code which uses @ExtendWith
of JUnit 5. I want to use a variable (which is a random number) that is generated in my original extension class using @before and @after and judge whether it is an even or odd number at the test. However, the getX
method returns 0 and the test class can never get the variable.
Here is my code. This is a test class. I would like to get variable "x" which is generated in SampleExtension
.
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.*;
@ExtendWith(SampleExtension.class)
public class Exercise {
//@RegisterExtension
SampleExtension sample = new SampleExtension();
//@RepeatedTest(5)
@Test
void test() {
System.out.println("test");
int x = sample.getX();
System.out.println(x);
assumingThat((x % 2 == 0), () -> {
System.out.println("this is an even number");
});
}
}
And this is an extension class.
import java.util.*;
import org.junit.jupiter.api.extension.*;
public class SampleExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback {
private int x;
@Override
public void afterEach(ExtensionContext Context) throws Exception {
System.out.println("afterEach");
System.out.println(this.x);
}
@Override
public void beforeEach(ExtensionContext Context) throws Exception {
System.out.println("beforeEach");
this.x = (int)(Math.random() * 5) 1;
}
@Override
public void afterAll(ExtensionContext Context) throws Exception {
System.out.println("afterAll");
this.x = 0;
}
@Override
public void beforeAll(ExtensionContext Context) throws Exception {
System.out.println("beforeAll");
this.x = 0;
}
int getX(){
return this.x;
}
}
The result.
Exercise > test() STANDARD_OUT
beforeEach
test
0
this is an even number
afterEach
4
Actually, @RegisterExtension
(where I comment out in the test class) worked as I wished instead of ExtendWith(someExtension.class)
and test class could get variable. But I would like to know how to do this using @ExtendWith
.
CodePudding user response:
Given the way how Jupiter's extension lifecycle works, instant variables are just not suited to transport any kind of state from one execution of an extension callback to the next. To cite Jupiter's user guide:
Usually, an extension is instantiated only once. So the question becomes relevant: How do you keep the state from one invocation of an extension to the next? The ExtensionContext API provides a Store exactly for this purpose.
So what you'll have to do is something similar to:
@Override
public void beforeEach(ExtensionContext context) throws Exception {
System.out.println("beforeEach");
int value = (int)(Math.random() * 5) 1;
getStore(context).put("MYVALUE", value);
}
@Override
public void afterEach(ExtensionContext Context) throws Exception {
System.out.println("afterEach");
int value = (int) getStore(context).get("MYVALUE");
System.out.println(value);
}
private Store getStore(ExtensionContext context) {
return context.getStore(Namespace.create(getClass()));
}
Mind that I haven't actually compiled the code so there may be bugs in it.