Spring Kafka ProducerRecord Mock Test - spring

ProducerRecord<Key,Value> producerRecord = new ProducerRecord<>(topicName, key,value);
ListenableFuture<SendResult<Key,Value>> future = kafkaTemplate.send(producerRecord);
Test Case
#Mock
ProducerRecord<Key,Value> producerRecord;
#Mock
ListenableFuture<SendResult<Key,Value>> future;
#Mock
private KafkaTemplate<Key,Value> producer;
When am mocking send method it will return null future object
when(producer.send(producerRecord)).thenReturn(future);
Solution I Found.
I Pass any(ProducerRecord.class) so i will trigger your method and return you future object
#Mock
ListenableFuture<SendResult<Key,Value>> future;
#Mock
private KafkaTemplate<Key,Value> producer;
when(producer.send(any(ProducerRecord.class))).thenReturn(future);

Besides mocking the KafkaTemplate#send method:
when(producer.send(producerRecord)).thenReturn(future);
You should instruct your class fixture implementation to initialize the mock objects. It should be a pre-instance step as follows:
#BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
}
It is common good practice to move mock configuration (common ones) to the set-up step as well:
#BeforeEach
void setup() {
MockitoAnnotations.initMocks(this);
SendResult<Key,Value> result = Mockito.mock(SendResult.class);
when(future.get()).thenReturn(result);
when(producer.send(producerRecord)).thenReturn(future);
}

Related

Junit and mockito with spring boot list is not available

hi every one i have some problem
i have a test class called TestUserService
#RunWith(MockitoJUnitRunner.class)
public class TestUserService {
#InjectMocks
UserService userService;
#Mock
InMemory inMemory;
#Before
public void init(){
MockitoAnnotations.initMocks(this);
}
#Test
public void registry(){
System.out.println("hi");
UserDto userDto=new UserDto(1L,"abed","alrhman",26);
UserDto userDto1=new UserDto(1L,"abdallah","almasre",27);
UserDto userDto2=new UserDto(1L,"bisher","alahmad",35);
UserDto userDto3=new UserDto(1L,"ibrahem","alrabe",32);
userService.registry(userDto);
userService.registry(userDto1);
userService.registry(userDto2);
userService.registry(userDto3);
System.out.println("\"registry\" = " + "registry");
verify(inMemory,times(0)).save(userDto.ToDTO(userDto));
verify(inMemory,times(1)).save(userDto1.ToDTO(userDto1));
verify(inMemory,times(0)).save(userDto2.ToDTO(userDto2));
verify(inMemory,times(0)).save(userDto3.ToDTO(userDto3));
}
}
when run the test i want save new user by UserService class and UserService will go to InMemory class
#Service
public class UserService implements IUserService {
private final InMemory inMemory;
public UserService(InMemory inMemory){
this.inMemory=inMemory;
}
#Override
public UserDto registry(UserDto userDto) {
User user=userDto.ToDTO(userDto);
User user1=inMemory.save(user);
return user.toEntity(user1);
}
}
the problem in InMemory Class it is a local repository has Map Called users and some other methods
after called registry(User user) method
the Map has it when debugger 'this' is not available
and the user param not receive into the save(User user) method and the debugger dont walk of any point check
private Map<Long,User> users=new HashMap<>();
#Override
public User save(User user) {
user.setId(1L);
users.put(1L,user);
return user;
}
and this is Image when debugger code
if you attention save(User user) dont has object or any value and users map not avalible
In your test, you are defining InMemory as a mock. A mock is an object that emulates the behavior of a real object according to how you configure such mock to behave. Having said that, your InMemory object in your test is not a real InMemory object, but a simple mock which means that its real code will not be called. Take a look at #Spy and consider replacing #Mock with it. Find more information in the following articles:
https://medium.com/swlh/what-is-the-difference-between-a-mock-and-a-stub-bd6b639e9fa5
https://www.baeldung.com/mockito-annotations#mock-annotation
in first step we must replace #Mock to Spy
and then we must change in when() method to when(spyInstance.method) and then we need called method has spyInstance.method to testing
this is my code after fixed you can see it
#Spy
InMemory inMemoryGet; // replace it from mock to spy
#InjectMocks
UserService userService;
#Before
public void init(){
MockitoAnnotations.initMocks(this);
}
#Test
public void registry(){
UserDto emp = new UserDto(1L,"Lokesh","Gupta",25); // add it
when(inMemoryGet.save(emp.ToDTO(emp))).thenReturn(emp.ToDTO(emp));
verify(inMemoryGet, times(0)).save(emp.ToDTO(emp)); // how many time invoke
userService.registry(emp); // called method from here
verify(inMemoryGet, times(1)).save(emp.ToDTO(emp));
System.out.println("\"Test\" = " + "Pass");
}

How to Mock jdbcTemplate.getJdbcTemplate().execute(); method?

My question is how to mock
jdbcTemplate.getJdbcTemplate().execute("TRUNCATE table TABLE_1");
method?
It's return value is void if I am right.
#RunWith(MockitoJUnitRunner.class)
public class Test {
#Mock
private NamedParameterJdbcTemplate jdbcTemplate;
...
//I tried this but of course it doesn't work
doReturn(void).when(jdbcTemplate).getJdbcTemplate().execute("TRUNCATE TABLE TABLE_1");
Any help is welcome.
From the comments, my understanding is that getJdbcTemplate is not final and you're interested in mocking its return value so you can verify method calls.
Here's the approach I'd take:
// create a mock for the return value
#Mock
JdbcTemplate template;
// create a mock for the factory
#Mock
NamedParameterJdbcTemplate jdbcTemplate;
#Before
public void setUp() {
// other initializations here
// configure the factory to return the above mocked template
when(jdbcTemplate. getJdbcTemplate()).thenReturn(template);
}
Now you should be able to verify on the template mock:
verify(template).execute("TRUNCATE TABLE TABLE_1");

Mockito test coming back as zero

I am trying to get call method called totalmoney() to get the total money in the h2 database but it always returns 0.
#RunWith(MockitoJUnitRunner.class)
public class MoneyTests {
#InjectMocks
MoneyServiceImplementation MoneyServiceImplementation;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void getAllMoney() {
long total_money = MoneyServiceImplementation.TotalMoney();
assertEquals("2000", total_money);
}}
But it will return the right amount of 2000 by:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Bean.xml");
MoneyService MoneyService = (MoneyService) context.getBean("MoneyServiceImplementation");
long total_money = MoneyService.TotalMoney();
So what am i doing wrong in the test that it will not work?
Mockito is not an dependency injection framework, don't expect this shorthand utility to inject a complex graph of objectsbe it mocks/spies or real objects.
Again, note that #InjectMocks will only inject mocks/spies created using the #Spy or #Mock annotation.
There are no any #Mock or #Spy annotated beans in your test, so all of the dependencies in the created MoneyServiceImplementation are null.

Mockito test case for repository layer EntityManager chained methods

Repository code to be tested using Mockito:
public List<X> findAll() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<X> criteriaQuery = criteriaBuilder.createQuery(X.class);
Root<X> policyRoot = criteriaQuery.from(X.class);
return entityManager.createQuery(criteriaQuery.select(policyRoot)).getResultList();
}
How to mock cretedQuery() and getResultList() methods of entityManger?
#Test
public void testCase() {
when(entityManager.getCriteriaBuilder()).thenReturn(new
CriteriaBuilderImpl(any()));
Query query = new QueryImpl(any(), any(), any());
when(entityManager.createQuery(anyString())).thenReturn(query);
when(query.getResultList()).thenReturn(attributeList);
}
It throws NullPointerException.
Use mocks. Make sure the entityManager is injectable in the class you try to test. For a unit test I would definitely do a test like this. It does not test the database, but it does test all the calls that are done and the general application logic. I agree you should also write an integration test that will test the 'real' database call and result.
#RunWith(MockitoJUnitRunner.class)
public class QueryTest {
#Mock
TypedQuery<X> query;
#Mock
CriteriaBuilderImpl criteriaBuilder;
#Mock
CriteriaQuery<X> criteriaQuery;
#Mock
Root<X> policyRoot;
#Mock
EntityManager manager; // This mock should be injected in the class that is been tested
#InjectMocks
TestClass sut; //System Under Test
#Test
public void test() {
when(manager.getCriteriaBuilder()).thenReturn(criteriaBuilder);
when(criteriaBuilder.createQuery(any(X.class)).thenReturn(criteriaQuery);
when(criteriaQuery.from(any(X.class)).thenReturn(policyRoot);
when(criteriaQuery.select(eq(policyRoot))).thenReturn(criteriaQuery);
when(manager.createQuery(eq(criteriaQuery)).thenReturn(query);
when(query.getResultList()).thenReturn(Collections.emptyList());
List<X> result = sut.findAll();
// now verify
verify(manager, times(1)).getCriteriaBuilder();
verify(criteriaBuilder, times(1)).createQuery(any(X.class));
// and so on
// now write your assertions
assertEquals(0, result.getSize());
}
}

CrudRepository test cases without inserting data in DB

I have one repository class which which implements CrudRepository. Then in service class I have auto wired this repositary. Then in controller class I have autowired this service.
I want to write test cases of controller Class. I am using below configuration.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class XYZControllerTest {
MockMvc mockMvc;
#Mock
private XYZController xyzController;
#Autowired
private TestRestTemplate template;
#Autowired
XYZRepository xyzRepository;
#Before
public void setup() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(xyzController).build();
}
#Test
public void testPanelShouldBeRegistered() throws Exception {
HttpEntity<Object> xyz = getHttpEntity("{\"name\": \"test 1\", \"email\": \"test10000000000001#gmail.com\","
+ " \"registrationNumber\": \"41DCT\",\"registrationDate\":\"2018-08-08T12:12:12\" }");
ResponseEntity<XYZ> response = template.postForEntity("/api/xyz", xyz, XYZ.class);
}
}
My problem is that when I run test case, data is going to insert in DB which is used for application. Can I test it without inserting data in DB.
Conceptually when we are testing services we mock repositories instead of injection.
You need to mock your repository and setup behavior for returning data.
An example :
#MockBean
XYZRepository xyzRepository;
#Test
public void test() {
// other mocks
//
when(xyzRepository.findAll()).thenReturn(Arrays.asList(new XYZ()));
// service calls
// assertions
}

Resources