Cannot solve databind.exc.InvalidDefinitionException: Cannot construct instance issue - spring

I have an issue with my post endpoint on my spring-boot server. I have model I want to send:
public class UpdateFiles {
private final String name;
private final ArrayList<File> fileList;
public UpdateFiles(String name, ArrayList<File> fileList) {
this.name = name;
this.fileList = fileList;
}
public String getName() {
return name;
}
public ArrayList<File> getFileList() {
return fileList;
}
}
Below there is a simple rest controller when i want return the same body as I received.
#RestController
public class RestClientController {
#RequestMapping(value = "/greeting", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST)
public HttpEntity<String> greeting(#RequestHeader(name = "Content-Type", required = true) String contentType,
#RequestHeader(name = "Accept", required = true) String accept,
#RequestBody UpdateFiles updateFilesRQ) throws IOException {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
ObjectMapper objectMapper = new ObjectMapper();
String requestString = objectMapper.writeValueAsString(updateFilesRQ);
return new ResponseEntity<>(
requestString, httpHeaders, HttpStatus.OK);
}
}
Here I have simple test to call post action.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {RestTemplateConfig.class, HttpClientConfig.class})
public class TestApplication {
#Autowired
RestTemplate restTemplate;
#Test
public void getEmployees() throws IOException {
final String uri = "http://localhost:8888/greeting";
ArrayList<com.licencjat.filesynchronizer.client.model.File> listOfFiles = new ArrayList<>();
listOfFiles.add(new com.licencjat.filesynchronizer.client.model.File("src/a", "01.01.01"));
listOfFiles.add(new com.licencjat.filesynchronizer.client.model.File("src/b", "02.02.02"));
UpdateFiles updateFiles = new UpdateFiles("yellow", listOfFiles);
ObjectMapper objectMapper = new ObjectMapper();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
String requestString = objectMapper.writeValueAsString(updateFiles);
HttpEntity<String> request = new HttpEntity<>(requestString, httpHeaders);
ResponseEntity<UpdateFiles> personResultAsJsonStr = restTemplate.postForEntity(uri, request, UpdateFiles.class);
System.out.println(personResultAsJsonStr);
}
}
After calling postForEntity I receive:
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.licencjat.filesynchronizer.client.model.UpdateFiles]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.licencjat.filesynchronizer.client.model.UpdateFiles` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 1, column: 2]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:246)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:228)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:104)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:998)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:981)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:741)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:449)
at com.licencjat.filesynchronizer.client.TestApplication.getEmployees(TestApplication.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.licencjat.filesynchronizer.client.model.UpdateFiles` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1589)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1055)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3258)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:240)
... 38 more
I know this might be simple question but I have been struggling with it for quite some time. I tried find my answer but none topics seemed related to my issue. I am doing something incorrect in the code? Do you know why I receive such an error?

There can be multiple solutions to overcome this problem.
If your class is mutable: define a default constructor and create setter methods.
public class UpdateFiles {
private final String name;
private final ArrayList<File> fileList;
// default constructor
public UpdateFiles() {
}
// AllArgsConstructor, getters and setters
}
If your class is immutable: annotate the constructor with #JsonCreator and the fields with #JsonProperty:
public class UpdateFiles {
private final String name;
private final ArrayList<File> fileList;
#JsonCreator
public UpdateFiles(#JsonProperty('name') String name, #JsonProperty('fileList') ArrayList<File> fileList) {
this.name = name;
this.fileList = fileList;
}
...
(A side note here: although there is no setters in UpdateFiles class, this does not means that is immutable. fileList is an ArrayList for which we have a getter, meaning that it is possible to be mutated from the outside.)

Related

Getting argument type mismtach error for #Recover annotation

I have a method with below definition
#Retryable(value = {
APICallFailedException.class,
IOException.class}, maxAttempts = TransformerConstants.GET_API_MAX_ATTEMPTS, backoff = #Backoff(delay = TransformerConstants.DELAY))
public <T> T getAPIResponse(String url, Class<T> classType)
where APICallFailedException.class extends Runtime exception class
I have a recover method that gets called when all retry attempts fail. It has the following definition
#Recover
public <T> T getBackendResponseFallback(RuntimeException exception, String getAPIURL,
Class<T> classType)
I changed the method definition of both the methods by adding a String parameter at the end so now they look like
#Retryable(value = {
APICallFailedException.class,
IOException.class}, maxAttempts = TransformerConstants.GET_API_MAX_ATTEMPTS, backoff = #Backoff(delay = TransformerConstants.DELAY))
public <T> T getAPIResponse(String url, Class<T> classType, **String APIUrl**)
#Recover
public <T> T getBackendResponseFallback(RuntimeException exception, String getAPIURL,
Class<T> classType, **String apiURL**)
After doing this when the retryable method fails and recover is called Argument mismatch exception is thrown
Below is the stacktrace
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.retry.annotation.RecoverAnnotationRecoveryHandler.recover(RecoverAnnotationRecoveryHandler.java:73)
at org.springframework.retry.interceptor.RetryOperationsInterceptor$ItemRecovererCallback.recover(RetryOperationsInterceptor.java:141)
at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:512)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:351)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:180)
at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:115)
at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at com.kroger.cxp.app.transformer.util.RestClientUtil$$EnhancerBySpringCGLIB$$6079045e.getAPIResponse(<generated>)
I want to understand why this is happening. Sprning doc says in #Recover best matching method is chosen based on the type of the first parameter and the type of the exception being handled. The closest match in the class hierarchy is chosen, so for instance if an IllegalArgumentException is being handled and there is a method whose first argument is RuntimeException, then it will be preferred over a method whose first argument is Throwable
getAPIResponse method calls another method inside it with definition
private HttpResponse<byte[]> callAPI(OkHttpClient okHttpClient, String url, Request request)
Is it possible that after adding the string parameter in Recover method parameter It tries to match with the second API call i.e callAPI instead of the intended one getAPIResponse
It works fine for me with your code; can you provide more details?
#SpringBootApplication
#EnableRetry
public class So68724467Application {
public static void main(String[] args) {
SpringApplication.run(So68724467Application.class, args);
}
#Bean
public ApplicationRunner runner(Foo foo) {
return args -> {
System.out.println(foo.getAPIResponse("foo", Object.class, "bar"));
};
}
}
#Component
class Foo {
#Retryable(value = {
IllegalStateException.class,
IOException.class }, maxAttempts = 3, backoff = #Backoff(delay = 2000))
public <T> T getAPIResponse(String url, Class<T> classType, String APIUrl) {
System.out.println("Retryable");
throw new IllegalStateException("test");
}
#Recover
public <T> T getBackendResponseFallback(RuntimeException exception, String getAPIURL,
Class<T> classType, String apiUR) {
System.out.println("Recover");
return (T) new Object();
}
}

How to Test a Kafka Client Configuration in SpringBoot

I have an a SpringBoot Application that is using Kafka with EhCache to perform Cache Synchronization among different MicroServices and Instances.
I'm using SpringBoot 2.2.4 with the matching Kafka-Client version.
How can I test that my Kafka Client is working correctly with an Embedded Kafka.
I've tried:
Test Class
#RunWith(SpringRunner.class)
#SpringBootTest()
#ActiveProfiles({"inmemory", "test", "kafka-test"})
#WebAppConfiguration
#DirtiesContext
public class CachePropagatorTest
{
private static final String topic = "com.allstate.d3.sh.test.cache";
//private static final String topic2 = "com.allstate.sh.test.alloc";
//#Rule
#ClassRule
public static final EmbeddedKafkaRule embeddedKafkaRule;
static
{
embeddedKafkaRule = new EmbeddedKafkaRule(1, true, topic);
embeddedKafkaRule
.getEmbeddedKafka().brokerListProperty("spring.kafka.bootstrap-servers");
}
//#Autowired
private EmbeddedKafkaBroker embeddedKafka;
#Autowired
KafkaTemplate<String, CacheMessage> kafkaTemplate;
#Autowired
KafkaSHProperties properties;
//#Autowired
#SpyBean
CachePropagator propagator;
//CachePropagationHelper propagator;
BlockingQueue<CacheMessage> records = new LinkedBlockingQueue<>();
/* read sent messages */
Consumer<Integer, CacheMessage> consumer;
private String topic1;
#Before
public void setUp() throws Exception
{
embeddedKafka = embeddedKafkaRule.getEmbeddedKafka();
topic1 = properties.getCacheTopic();
assertThat(topic1, is(topic));
//embeddedKafka.getEmbeddedKafka().addTopics(topic1);
try { embeddedKafka.addTopics(topic1); }
catch (KafkaException Ignored) { }
Mockito.doAnswer(new Answer<Void>()
{
#Override
public Void answer(InvocationOnMock invocation) throws Throwable
{
System.out.println("Cache Message Receive");
records.add((CacheMessage) invocation.getArgument(0));
return (Void)invocation.callRealMethod();
}
}).when(propagator).receive(ArgumentMatchers.any(),
ArgumentMatchers.anyString());
//prove raw template usage
CacheMessage cm = new CacheMessage("Test","Test","put",
true,"");
kafkaTemplate.send(topic1, cm);
Map<String, Object> consumerProps =
KafkaTestUtils.consumerProps(properties.getCacheConsumptionGroup(),
"false", embeddedKafka);
DefaultKafkaConsumerFactory<Integer, CacheMessage> cf =
new DefaultKafkaConsumerFactory<Integer, CacheMessage>(consumerProps);
consumer = cf.createConsumer();
embeddedKafka.consumeFromAllEmbeddedTopics(consumer);
Set<String> topics = embeddedKafka.getTopics();
assertThat(topics.size(),is(1) );
assertThat(topics,hasItem(topic1) );
//prove sent message received
ConsumerRecord<Integer, CacheMessage> received =
KafkaTestUtils.getSingleRecord(consumer, topic1, 30000);
assertThat(received.value(), is("Test"));
}
#After
public void tearDown() throws Exception { }
#Test
public void putExperiment() throws Exception
{
Date now = new Date();
JsonNode emptyNode = new ObjectMapper().readTree("");
List<BucketDetail> buckets = new ArrayList<>();
buckets.add(new BucketDetail("99-1", "Kafka Bucket 1",
0.5, emptyNode));
buckets.add(new BucketDetail("99-2", "Kafka Bucket 2",
0.5, emptyNode));
buckets.add(new BucketDetail());
ExperimentDetail exp = new ExperimentDetail("99", 1,
"KafkaTest",
"SH_TEST_PROFILE_9",
buckets, LifecycleStage.CONFIGURED,
now, null, "Mete Test Notes");
propagator.putExperiment(exp);
//TODO: test the allocation was correct
ConsumerRecord<Integer, CacheMessage> received =
KafkaTestUtils.getSingleRecord(consumer, topic1, 10000);
//TODO: how much should this verify in the message
assertThat(received.value().getAction(), is("put"));
assertThat(received.value().getItem().toString(),
containsString(exp.getExperimentID()));
}
}
Kafka in application-test.yml
spring:
kafka:
bootstrap-servers: localhost:2181
listener:
#add topics after start
missing-topics-fatal: false
properties:
sasl:
kerberos:
service:
name: kafka
security:
protocol: SASL_PLAINTEXT
consumer:
properties:
spring:
json:
trusted:
packages: com.allstate.d3.sh.commons.messaging
bootstrap-servers: localhost:2181
auto-offset-reset: latest
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
producer:
bootstrap-servers: localhost:2181
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
profiles:
active: inmemory,kafka-test
When run tests it fails in the Unit setup() method with
java.lang.IllegalStateException: No records found for topic
at org.springframework.kafka.test.utils.KafkaTestUtils.getSingleRecord(KafkaTestUtils.java:187)
at com.allstate.d3.sh.execution.event.CachePropagatorTest.setUp(CachePropagatorTest.java:169)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:106)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:66)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:117)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:748)
So why can't I find any sent records for the topic?
UPDATE
The Answer by #QuickSilver below pointed out running in parrallel.
Could my #SpyBean CachePropagator propagator; be interfering with my tests.
Cache Propegator has a listener method defined like so:
#KafkaListener(topics = "#{kafkaSHProperties.cacheTopic}",
groupId = "#{kafkaSHProperties.cacheConsumptionGroup}")
public void receive(#Payload CacheMessage message,
#Header(KafkaHeaders.RECEIVED_MESSAGE_KEY) String key)
{
if (!envName.equals(message.getEnv())) { return; }
log.info("07e9d084-1b8c-4c4c-b9be-9e7bb2716c3c -- Cache sync message: {}, {}, {}",
key, message.getEnv(), message.getCacheName());
processMessage(message);
}
Could that be grabbing my messages? If so, shouldn't they still be available on the broker? If not is that a setting I can change?
Can you please below items in your code,
the Kafka-Consumer is started before the Kafka-Producer and continues to run even after Kafka-Producer publishes the record
If the Kafka-Consumer starts after Kafka-Producer then it should poll from beginning offset.
Below test on my machine
#SpringBootTest
#RunWith(SpringRunner.class)
public class TestKafkaConfig {
#ClassRule
// By default it creates two partitions.
public static KafkaEmbedded embeddedKafka = new KafkaEmbedded(1, true, TOPIC_NAME);
private static String TOPIC_NAME = "testTopic";
#Test
public void testKafkaConfig() throws InterruptedException, ExecutionException {
Map<String, Object> senderProps = KafkaTestUtils.producerProps(embeddedKafka);
KafkaProducer<Integer, String> producer = new KafkaProducer<>(senderProps);
producer.send(new ProducerRecord<>(TOPIC_NAME, 0, 0, "ABC")).get();
producer.send(new ProducerRecord<>(TOPIC_NAME, 0, 1, "XYZ")).get();
Map<String, Object> consumerProps = KafkaTestUtils.consumerProps("testConsumer", "false", embeddedKafka);
consumerProps.put("auto.offset.reset", "earliest");
final List<String> receivedMessages = Lists.newArrayList();
final CountDownLatch latch = new CountDownLatch(2);
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(() -> {
KafkaConsumer<Integer, String> kafkaConsumer = new KafkaConsumer<>(consumerProps);
kafkaConsumer.subscribe(Collections.singletonList(TOPIC_NAME));
try {
while (true) {
ConsumerRecords<Integer, String> records = kafkaConsumer.poll(100);
records.iterator().forEachRemaining(record -> {
receivedMessages.add(record.value());
latch.countDown();
});
}
} finally {
kafkaConsumer.close();
}
});
latch.await(10, TimeUnit.SECONDS);
assertTrue(receivedMessages.containsAll(Arrays.asList("ABC", "XYZ")));
}
}

Acceptance Test with MockMultipartFile, and HttpMessageConversionException occurs

I tried AcceptanceTest with MockMultipartFile class in springboot and HttpMessageConversionException occurs.
and I saw many code work with File Object but as you see my dto contains MultipartFile..
could you know me why It doesn't works? and How to fix it?
It is jackson converting error, so I check all of get~ method and
I tried for making CustomMultipartFile and override getInputStream method and attach #JsonIgnore
but it make another error and doesn't work
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class java.io.ByteArrayInputStream]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.mock.web.MockMultipartFile["inputStream"])
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:293)
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.writeInternal(AbstractGenericHttpMessageConverter.java:112)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:227)
at org.springframework.http.converter.FormHttpMessageConverter.writePart(FormHttpMessageConverter.java:417)
at org.springframework.http.converter.FormHttpMessageConverter.writeParts(FormHttpMessageConverter.java:393)
at org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:373)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:277)
at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:95)
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:948)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:733)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:579)
at org.springframework.boot.test.web.client.TestRestTemplate.exchange(TestRestTemplate.java:774)
at com.mappractice.demo.acceptanceTest.AcceptanceTest.sendFile(AcceptanceTest.java:51)
at com.mappractice.demo.acceptanceTest.ImageAcceptanceTest.이미지_생성_API_성공(ImageAcceptanceTest.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.mock.web.MockMultipartFile["inputStream"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:313)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1396)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:913)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:287)
... 45 more
TEST CODE
public class ImageAcceptanceTest extends AcceptanceTest {
private static final String API_IMAGE_URI = "/api/image";
private static MockMultipartFile content;
private static Image image;
private static PositionedImageDTO positionedImageDTO;
#BeforeClass
public static void init() {
content = new MockMultipartFile("file",
"ded.png",
"image/png",
"datdedadsdwdssdwa".getBytes()
);
image = new Image(1L, "테스트 이미지", "12kl312nlk3".getBytes(), new Location("12.1234567", "12.1234566"));
positionedImageDTO = new PositionedImageDTO("테스트 이미지", content, "12.1234567", "12.1234566");
}
#Test
public void image_create_API_success() {
MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>();
parameters.add("fileName", "테스트 이미지");
parameters.add("file", content);
parameters.add("xIndex", "123");
parameters.add("yIndex", "454");
ResponseEntity<Image> responseEntity = sendFile(API_IMAGE_URI, parameters, Image.class);
assertThat(responseEntity.getBody().getName()).isEqualTo("테스트 이미지");
}
...
Controller CODE
#RestController
#RequestMapping("/api/image")
public class ApiImageController {
...
#PostMapping("")
public ResponseEntity<Image> create(#ModelAttribute PositionedImageDTO positionedImageDTO){
Image image = imageService.create(positionedImageDTO);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setLocation(URI.create("/api/image/"+image.getId()));
return new ResponseEntity<>(image, headers, HttpStatus.CREATED);
}
...
}
DTO CODE
#Getter
#Setter
#NoArgsConstructor
#ToString
public class PositionedImageDTO {
#NotEmpty
private String fileName;
#NotEmpty
private MultipartFile file;
#NotNull
private String xIndex;
#NotNull
private String yIndex;
public PositionedImageDTO(String fileName, MultipartFile file, String xIndex, String yIndex) {
this.fileName = fileName;
this.file = file;
this.xIndex = xIndex;
this.yIndex = yIndex;
}
public String getExtentionFormat() {
return "." + file.getContentType().split("/")[1];
}
}

Java.lang.NullPointerException what's wrong

It says error in this method a null pointer Exception
#Test
public void showBookListPage() throws Exception {
List<Book> expectedBookList = bookService.findAll();
BookService bookService = mock(BookService.class);
when( bookService.findAll()).thenReturn(expectedBookList);
BookController bookController = new BookController(bookService);
MockMvc mockMvc = standaloneSetup(bookController).build();
mockMvc.perform(get(" /book/bookList"))
.andExpect(view().name("bookList"))
.andExpect(model().attributeExists("bookList"))
.andExpect(model().attribute("bookList", hasItems(expectedBookList.toArray())));
}
}
Other than that everything seems to be correct
This is the error I got after mocking the book service first before call
java.lang.IllegalStateException: missing behavior definition for the preceding method call:
BookService.findAll()
Usage is: expect(a.foo()).andXXX()
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:42)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94)
at com.sun.proxy.$Proxy134.findAll(Unknown Source)
at com.admintest.controller.BookControllerTest.showBookListPage(BookControllerTest.java:101)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springf
And this is my edit to the test method
#Test
public void showBookListPage() throws Exception {
BookService bookService = mock(BookService.class);
List<Book> expectedBookList = bookService.findAll();
when(bookService.findAll()).thenReturn(expectedBookList);
BookController bookController = new BookController(bookService);
MockMvc mockMvc = standaloneSetup(bookController).build();
mockMvc.perform(get(" /book/bookList"))
.andExpect(view().name("bookList"))
.andExpect(model().attributeExists("bookList"))
.andExpect(model().attribute("bookList", hasItems(expectedBookList.toArray())));
}
And by the way this is the controller
#RequestMapping("/bookList")
public String bookList(Model model) {
List<Book> bookList = bookService.findAll();
model.addAttribute("bookList", bookList);
return "bookList";
}
You have to mock the bookService before using it. Not after it's usage. So do the mocking of bookService in #BeforeMethod

How to testing Spring validator with Junit and Mockito

I have a Spring Validator:
#Component
public class AddClientAccountValidator implements Validator {
#Autowired
private ValidatorUtils validatorUtils;
#Override
public boolean supports(Class<?> clazz) {
return UserDto.class.equals(clazz);
}
#Override
public void validate(Object target, Errors errors) {
UserDto user = (UserDto) target;
validatorUtils.setParam(errors, user);
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "username.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "password.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "confirmPassword",
"confirmPassword.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "firstName.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "lastName.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "personalId", "personalId.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "city", "city.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "address", "address.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "email.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "phone", "phone.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "contribution", "contribution.required");
validatorUtils.validateAddClientAccount();
}
}
In above Validator have inject to ValidatorUtils class:
#Component
class ValidatorUtils {
#Autowired
private PersonalIdValidator personalIdValidator;
private Errors errors;
private UserDto user;
void setParam(Errors errors, UserDto user) {
this.errors = errors;
this.user = user;
}
void validateAddClientAccount() {
validateAccount();
validContributionAccount();
}
private void validateAccount() {
validUsername();
validPassword();
validFirstName();
validLastName();
validPersonalId();
validCity();
validAddress();
validEmail();
validPhone();
}
public void validateChangePassword() {
validChangePassword();
}
private void validUsername() {
if (!user.getUsername().isEmpty()) {
String username = user.getUsername();
if ((username.length() < 3) || (username.length() > 40)) {
errors.rejectValue("username", "username.format");
}
}
}
private void validPassword() {
if (!user.getPassword().isEmpty()) {
String password = user.getPassword();
if ((password.length() < 3) || (password.length() > 40)) {
errors.rejectValue("password", "password.format");
}
if (!password.equals(user.getConfirmPassword())) {
errors.rejectValue("confirmPassword", "password.confirm");
}
}
}
private void validFirstName() {
if (!user.getFirstName().isEmpty()) {
String firstName = user.getFirstName();
String regex = "[A-ZŁ{1}]+[a-zł]+";
boolean validFirstName = Pattern.matches(regex, firstName);
if ((firstName.length() < 3) || (firstName.length() > 40) || !validFirstName) {
errors.rejectValue("firstName", "firstName.format");
}
}
}
private void validLastName() {
if (!user.getLastName().isEmpty()) {
String lastName = user.getLastName();
String regex = "[A-ZĆŁŚŻŹ{1}]+[a-ząćęłńóśżź]+";
String regexWithTwoLastName = "[A-ZĆŁŚŻŹ{1}]+[a-ząćęłńóśżź]++[\\s]+[A-ZĆŁŚŻŹ{1}]+[a-ząćęłńóśżź]+";
boolean validLastName = Pattern.matches(regex, lastName);
boolean validWithTwoLastName = Pattern.matches(regexWithTwoLastName, lastName);
if ((lastName.length() < 3) || (lastName.length() > 40)
|| (!validLastName && !validWithTwoLastName)) {
errors.rejectValue("lastName", "lastName.format");
}
}
}
this class have more validator for field but I skipped it.
I want to test my Validator class use Junit or eventually mockito. I write this test class:
#RunWith(MockitoJUnitRunner.class)
public class AddClientAccValidatorTest {
#InjectMocks
private AddClientAccountValidator validator;
#Mock
private ValidatorUtils validatoUtils;
private UserDto userDto;
public Errors errors;
#Before
public void setUp() {
UserDto userDto = new UserDto();
errors = new BeanPropertyBindingResult(userDto, "userDto");
}
#Test
public void testValidate() {
validator.validate(userDto, errors);
assertFalse(errors.hasErrors());
}
}
But when i run my test i get following Failet trace:
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:86)
at org.junit.Assert.assertTrue(Assert.java:41)
at org.junit.Assert.assertFalse(Assert.java:64)
at org.junit.Assert.assertFalse(Assert.java:74)
at pl.piotr.ibank.validator.AddClientAccValidatorTest.testValidate(AddClientAccValidatorTest.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Why I get this error? I get error in this line:
errors = new BeanPropertyBindingResult(userDto, "userDto");
And my second problem is that I can't declare multiple RunWith annotation. When I add:
#RunWith(MockitoJUnitRunner.class)
I can't parametrized my test using #RunWith(Parameterized.class)
How to solve it?
Anyone can help me? Maybe my approach is bad? What is best way to test Spring Validator with Junit?
You can run your test successfully without Mockito. The following code works with Spring #Configuration class (spring-test as dependency is required):
package foo.bar;
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class AddClientAccValidatorTest {
#Configuration
static class ContextConfiguration {
#Bean
public AddClientAccountValidator validator() {
return new AddClientAccountValidator();
}
#Bean
public ValidatorUtils validatorUtils() {
return new ValidatorUtils();
}
}
#Autowired
private AddClientAccountValidator validator;
private UserDto userDto;
public Errors errors;
#Before
public void setUp() {
userDto = new UserDto();
userDto.setLastName("Doe");
userDto.setFirstName("John");
userDto.setUsername("username");
userDto.setPhone("phone");
userDto.setPassword("password");
userDto.setConfirmedPassword("password");
userDto.setEmail("email");
userDto.setContribution("contribution");
userDto.setAddress("address");
userDto.setCity("city");
userDto.setPersonalId("personalId");
errors = new BeanPropertyBindingResult(userDto, "userDto");
}
#Test
public void testValidate() {
validator.validate(userDto, errors);
assertFalse(errors.hasErrors());
}
}
You don't need to Mock anything. While validating , we need the object which we want to validate and the errors. Create an object with required fields to validate and the errors object. For example,
#Test
public void shouldReturnErrorsWhenCustomObjectIsNull() {
CustomValidator customValidator = new CustomValidator();
Employee employee = new Employee();
employee.setEmployeeFirstname("empName")
Errors errors = new BeanPropertyBindingResult(employee, "employee");
customValidator.validate(employee, errors);
List<ObjectError> allErrors = errors.getAllErrors();
assertTrue("Errors list size should not be null : ", allErrors.size() > 0);
assertTrue(errors.hasErrors());
assertNotNull( errors.getFieldError("empName") );
}

Resources