Reputation: 73
There is a @Value annotated constant, which is not getting initialized when running test, it throws NullPointerException when it is required inside constructor.
Sample Class to be tested:
class TestClass {
@Value("${test.value1}")
private String value1;
private final TestTemplate testTemplate;
public TestClass(TestTemplateBuilder builder) {
testTemplate = builder.someMethod(value1).build();
}
---
}
Sample Test Class:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestClass.class)
@SpringBootTest
class TestClassTest {
@MockBean
TestTemplateBuilder builder;
@Autowired
TestClass testClass = new TestClass(testTemplate);
@Before
public void setUp() {
ReflectionTestUtils.setField(testClass, "value1", "VALUE");
Mockito.when(builder.build()).thenReturn(new TestTemplate());
}
---
}
Things tried, but nothing worked:
application.properties
file with required value.application-test.properties
and added @TestPropertySource(locations="classpath:application-test.properties")
.@SpringBootTest(properties = { "test.value1=VALUE" })
I have tried some other things also, but what i got is NullPoiterException
at someMethod(value1)
.
Versions:
Upvotes: 5
Views: 10035
Reputation: 21
If @Before is not working, then try with @BeforeEach. It worked for me.
`@BeforeEach
public void setUp() {
ReflectionTestUtils.setField(yourInstanceClass, "fieldName", "fieldValue");
}`
Upvotes: 2
Reputation: 656
Just to make sure (because in the question, it's doesn't showed):
class TestClass
is Spring bean
(Component, Service...)?
Edit (TestClass
is Component):
This is not how Spring bean
are created;
If constructor of TestClass
require @Value then only Spring will guarantee that before instantiating TestClass
the test.value1
value is available.
So you can add to the constructor @Value("${test.value1}")String value1
and set the value1
property.
Please read the ways of how Spring
inject.
Upvotes: 1
Reputation: 73
I was not able to solve the main issue, but i fulfilled my requirement like this.
class TestClassTest {
TestClass testClass;
@Before
public void setUp() {
TestTemplateBuilder builder = Mockito.mock(TestTemplateBuilder.clsss);
TestTemplateBuilder builder1 = Mockito.mock(TestTemplateBuilder.clsss);
Mockito.when(builder.someMethod(nullable(String.class))).thenReturn(builder1);
Mockito.when(builder1.build()).thenReturn(new TestTemplate());
testClass = new TestClass(builder);
}
---
}
This might not be the correct way of doing.
Upvotes: 0
Reputation: 131
The reason you are getting NullPointerException is that the value injection occurs after the constructor call. To prevent this you can use spring life cycle hooks to initialize your class after the constructor call.
Upvotes: 0