Acceptance Test with MockMultipartFile, and HttpMessageConversionException occurs - spring-boot

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];
}
}

Related

MockMvc peform is return nullPointerException in integration tests

I'm trying to run integration tests for my Spring project, it's a simple get method that returns a String output from the DB for the id given. But I keep getting a NullPointerException on the Mockmvc in the MockMvc.perform within my tests.
Here is the test:
#WebMvcTest(OutputController.class)
public class OutputControllerTests {
#Autowired
private MockMvc mockMvc;
#MockBea
OutputService outputService;
#Test
public void returnOutputForValidId() throws Exception {
OutputService service = Mockito.mock(OutputService.class);
when(service.findOutputById("TEST")).thenReturn("Test output");
String getOutputMapping = "/output/{systemID}";
String id = "TEST";
mockMvc.perform(get(getOuputMapping, id))
.andDo(print()).andExpect(status().isOk())
.andExpect(content().string("Test output"));
}
Here is the controller - OutputController:
#RestController
public class OutputController {
private final OutputService outputService;
public OutputController(OutputService outputService) {
this.outputService = outputService;
}
#GetMapping("/output/{id}")
#CrossOrigin
public String getOutputByID(#PathVariable String Id) {
String output = outputService.findOutputById(Id);
return output;
}
}
The full error is :
java.lang.NullPointerException
at .com.output.OutputControllerTests.returnOutputForValidId(OutputControllerTests.java:37)
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:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
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)
You don't need to autowire MockMvc object. Try with this instead:
import org.junit.jupiter.api.BeforeEach;
//...
private MockMvc mockMvc;
//...
#BeforeEach
public void setUp(WebApplicationContext context) {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}

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

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.)

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")));
}
}

Null after #InjectMocks in Mockito Junit

I am having some troubles passing a dependancy while unit testing with JUnit.
Consider these pieces of code:
This is the dependacy injecton into the class which i want to test, lets call it Service.
error log trace
java.lang.NullPointerException
at com.example.demo.service.ServiceClass.getCustomerById(ServiceClass.java:50)
at com.example.demo.service.ServiceClassTest.getCustomerByIdTest(ServiceClassTest.java:46)
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.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
ServiceClass
#Service
public class ServiceClass {
public static final String CRM_JPA_URI = "http://localhost:9000/api/tickets/";
#Autowired
RestTemplate restTemplate;
public Customer getCustomerById(int customerId) {
ResponseEntity<Customer> entity = restTemplate.getForEntity(CRM_JPA_URI +"ticket/{customerId}",
Customer.class, customerId);
return entity.getBody();
}
}
ServiceClassTest
#RunWith(MockitoJUnitRunner.class)
public class ServiceClassTest {
#Mock
RestTemplate mockRestTemplate;
#InjectMocks
ServiceClass serviceClass;
/**
* getCustomerByIdTest
*/
#Test
public void getCustomerByIdTest(){
Customer customer = new Customer();
customer.setPassengerName("Ramesh");
customer.setBookingDate("09/09/2019");
customer.setDestStation("pamur");
customer.setEmail("r#gmail.com");
customer.setSourceStation("ongole");
Mockito.lenient().when(mockRestTemplate.getForEntity("http://localhost:9000/api/tickets/ticket/1", Customer.class)).
thenReturn(new ResponseEntity<Customer>(customer,HttpStatus.OK));
System.out.println("object is--->"+serviceClass.getCustomerById(1));
assertEquals(customer, serviceClass.getCustomerById(1));
}
}
Try calling
MockitoAnnotations.initMocks(this);
in your test method or #Before setup() method

NullPointerException in the BeforeClass (spring boot)

I want to make an insert in my DB before all tests just once. That's what I'm trying to do in the setUp() method. But got nullpointer. Spring boot version is 1.5.1.RELEASE. Any ideas?
This is from my test class:
#Autowired
private static UserRepository userRepository;
#BeforeClass
public static void setUp() {
User user = User.
.builder()
.id(10)
.name("John")
.build();
userRepository.deleteAll(); //NullPointerException at this step
userRepository.save(user);
}
This is my entity class:
#Entity
#Table(schema="test", name = "TBL_USERS")
#AllArgsConstructor
#Builder
#Data public class User implements Persistable<String>{
#Id
#Column(name = "ID", columnDefinition = "decimal")
private String id;
#Column(name = "NAME", columnDefinition = "char", nullable = false)
private String name;
...
}
This is the interface:
public interface UserRepository extends JpaRepository<User, String> {}
The stack trace:
java.lang.NullPointerException
at com.company.myapp.get.GetUserTest.setUp(GetUserTest.java:58)
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:497)
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.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:191)
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:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
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:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Short answer: You can not inject static UserRepository (#Autowired)
Please read here Reason we could not inject static field
It doesn't look like you initialized userRepository to anything in your beforeClass method before calling deleteAll() on it. That's why you got your NPE.
Is your test class annotated with #RunWith(SpringRunner.class)?
You need to do something like this..
#RunWith(SpringRunner.class)
#SpringBootTest
public class XXXTest {
#Autowired
private UserRepository userRepository;
#Before
public void setUp() {
......
}

Resources