Issue
there's a problem here!
In my application I have a Consumer (kafka) that uses a Facade that uses a Client that calls a rest Api with RestTemplate
I want (have) to test the whole flow excluded the rest call. so I've tried to mock RestTemplate but without success -_-
here an example of my classes
@Service
public class KafkaConsumer{
@Autowired MyFacade facade;
@KafkaListener
public void onMessage(){
facade.awesomeMethod();
}
}
@Service
public class MyFacade{
@Autowired MyClient client;
public void awesomeMethod(){
client.callApi();
}
}
@Service
public class MyClient{
@Autowired RestTemplate restTemplate;
public void callApi(){
restTemplate.exchange(.....);
}
}
now I'm tring to build a test with mock but something goes wrong and RestTemplate call real server
here test class
@ActiveProfile("test")
@RunWith(SpringRunner.class)
@SpringbootTest
@EmbeddedKafka
public class MyFailTest{
@Mock RestTemplate restTemplate;
@InjectMocks MyFacade facade;
@InjectMocks MyClient client;
@InjectMocks KafkaConsumer consumer;
@Autowired KafkaProducer producer;
@Test
public void test(){
Mokito.when(restTemplate.exchange(....)).thenReturn(new ResponseEntity<Void>(HttpStatus.OK);)
producer.send("My Kafka Message");
}
}
here my test dependecies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.11.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
Junit4 and Springboot 2.6.7
I think I'm failing in @Mock and @InjecMock logic, i've tried some combination of them ; ) but without success
Solution
thanks to @geobreze comment I drilled down into @MockBean. It was a way tried on my thousands tries but I copied some code without really understand what it was coping
At the end I've used @SpyBean because @MockBean mocks all methods class. To semplify implementation I've mocked Client object, exchenge of RestTemplate it is a little bit complex, I didn't want fall in other stupid error.
It is not useful declare all classes chain, so I've removed facade and I've used @autowired annotation rather than @InjectMock
here my test
@ActiveProfile("test")
@RunWith(SpringRunner.class)
@SpringbootTest
@EmbeddedKafka
public class MySuccessfullTest{
@SpyBean MyClient client;
@Autowired KafkaConsumer consumer;
@Autowired KafkaProducer producer;
@Test
public void test(){
MyClientResponse responseObject = MyClientResponse();
Mokito.doReturn(responseObject).when(client).callApi();
producer.send("My Kafka Message");
}
}
Answered By - Ging3r
Answer Checked By - Senaida (JavaFixing Volunteer)