this is my juntt 5 controller test cases class
@ExtendWith(SpringExtension.class)
@WebMvcTest(DomainController.class)
class DomainControllerTest {
@Autowired private MockMvc mockMvc;
@MockBean private DomainHandler domainHandler;
@Test
void save() throws Exception {
when(domainHandler.save(any(DomainRequest.class))).thenReturn(createBaseResponseForSave());
final var requestBuilder =
post("/api/domain")
.contentType(MediaType.APPLICATION_JSON)
.content(DomainTestData.saveRequestJson());
mockMvc
.perform(requestBuilder)
.andExpect(status().isOk())
.andExpect(content().json(DomainTestData.saveResponseJson()))
.andReturn();
}
}
this is my data creation class
public class DomainTestData {
public static Domain domain = createDomain();
public static final List<Domain> domainList = createDomainList();
private static MessageSource messageSource;
public static String getMessage(String key) {
return messageSource.getMessage(key, null, Locale.getDefault());
}
public static BaseResponse createBaseResponseForSave() {
String successMessage = getMessage("api.success.response");
return new BaseResponse<>(
1001,
successMessage,
new DomainResponse("Java", "bb11f2a9-a38a-45f5-92a2-3dbcefe8cb04")
);
}
public static String convertObjectToFormattedJson(Object dataObject)
throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(dataObject);
}
public static String saveResponseJson() throws JsonProcessingException {
return convertObjectToFormattedJson(createBaseResponseForSave());
}
}
this is my MessageSource Configration class in
exam-engine-core/src/main/java/com/testiqo/exam/engine/config/MessagePropertiesConfiguration.java
@Configuration
public class MessagePropertiesConfiguration {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource =
new ReloadableResourceBundleMessageSource();
messageSource.setBasenames(
"classpath:/messages/api_error_messages",
"classpath:/messages/api_response_messages",
"classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocalValidatorFactoryBean getValidator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
}
this is my api_response_messages.properties file in
exam-engine-core/src/main/resources/messages/api_response_messages.properties
api.success.response=Success
api.successfully.saved.response={0} : {1} is saved successfully
api.successfully.updated.response={0} : {1} is updated successfully
api.successfully.deleted.response={0} is deleted successfully
api.not.found={0} not found
api.no.data.found=No data found for {0}
api.no.data.found.for.uid=No {0} found for given uid {1}
api.no.data.found.for.given.search.criteria=No data found for given search criteria
api.question.successfully.added.exam.response = Question successfully added in exam
api.exam.result.fetch = The exam result has been successfully fetched.
api.question.successfully.removed.exam.response = The question has been successfully removed from the exam
api.exam.view.response = The exam details have been fetched successfully
exam.not.found= {0} details not found for {1}
domain.not.found= {0} details not found for {1}
question.domain.not.found = Topic does not exist in domain
when i run my test cases facing null-pointer error on MessageSource
This is my error
Cannot invoke "org.springframework.context.MessageSource.getMessage(String, Object[], java.util.Locale)" because "com.testiqo.exam.engine.utils.domain.DomainTestData.messageSource" is null
java.lang.NullPointerException: Cannot invoke "org.springframework.context.MessageSource.getMessage(String, Object[], java.util.Locale)" because "com.testiqo.exam.engine.utils.domain.DomainTestData.messageSource" is null
at com.testiqo.exam.engine.utils.domain.DomainTestData.getMessage(DomainTestData.java:29)
at com.testiqo.exam.engine.utils.domain.DomainTestData.createBaseResponseForSave(DomainTestData.java:33)
at com.testiqo.exam.engine.controller.DomainControllerTest.save(DomainControllerTest.java:47)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
I need to use MessageSource for get message so how to use MessageSource
I supposed, you've got this NPE because the class DomainControllerTest
calls the static method createBaseResponseForSave()
from the class DomainTestData
that use the static class member messageSource
. The NPE occures because Spring cannot inject the bean messageSource
into a static context.
To avoid the NPE, it's enough for you to just make the class DomainTestData
non-static -> make class member messageSource
non-static which will allow Spring to inject the bean messageSource
through a constructor.
Also you can try to define the bean messageSource
as a static bean and this can help too. But I'm not sure it will work.
UPD
Related changes:
The first change is to make the DomainTestData
class non-static. To do this, youd need to remove the static
special word in the line private static MessageSource messageSource;
and do the same for two methods: getMessage(...)
and createBaseResponseForSave()
. The next step is to create a constructor for this class as follows:
public DomainTestData(MessageSource messageSource) {
this.messageSourcec = messageSource;
}
The second change is to tell Spring to inject the messageSource
bean into the DomainTestData
class. To do this it's enough to add the @Component
annotation above the class declaration as follows:
@Component
public class DomainTestData {
// ...
}
And the final step is to inject the changed DomainTestData
class into the DomainControllerTest
and change the static method call of this class to a call via class-member as follows:
class DomainControllerTest {
// ...
@Autowired private DomainTestData domainTestData;
// ...
@Test
void save() throws Exception {
when(domainHandler.save(any(DomainRequest.class))).thenReturn(domainTestData.createBaseResponseForSave());
// ...
}