0

How can i write junit test for void method?

i have following method in service layer

    @Override
    public void add(Demo demo) throws ApiError {
     if (!repository.existsByNameAndAge(demo.getName(), demo.getAge())) {
                throw new ApiError(HttpStatus.BAD_REQUEST, "bad request");
            }
            Integer count = newRepository.countByName(cart.getName());
            newRepository.save(new Demo(demo.getName(), demo.getAge(), demo.getCity(), count));
   }

here is my service method and i want to do junit test case for it. but it's return type is void. i want to do testing of each statment. how can i done junit testing of this please suggest me..

Alien
  • 15,141
  • 6
  • 37
  • 57
  • 1
    With mockito mock repository and newRepository so you can verify the calls made to them. Also you could verify the exception you are throwing – Willem Dec 28 '20 at 14:22
  • Here is a possible answer to your question https://stackoverflow.com/questions/21901368/mockito-verify-order-sequence-of-method-calls – Andres Sacco Dec 28 '20 at 14:30

2 Answers2

1

Sorry I wrote the answer for Junit5 and then noticed you tagged Junit4, I will post it anyway, the idea is the same and differences in the code should be minor. What you can do is using Mockito to inject mocks and verify that the methods are called with the parameters you expect them be called. I would write 2 test cases: one to check the exception is thrown and the repositories are not called and another one to check the repository is properly saving:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class MyServiceTest {

    @Mock
    private Repo repository;
    @Mock
    private NewRepo newRepository;
    @Captor
    private ArgumentCaptor<Demo> demoCaptor;
    @InjectMocks
    private MyService service;

    @Test
    void throwsIfDoesNotExistForGivenNameAndAge() {
        when(repository.existsByNameAndAge("name", 12)).thenReturn(false);
        assertThrows(ApiError.class, () -> service.add(new Demo("name", 12, "city", 10)));
        verify(newRepository, times(0)).countByName(anyString());
        verify(newRepository, times(0)).save(any(Demo.class));
    }

    @Test
    void savesToNewRepositoryWithRightValues() {
        when(repository.existsByNameAndAge("name", 12)).thenReturn(true);
        when(newRepository.countByName("cart")).thenReturn(10);
        service.add(new Demo("name", 12, "city", 10));
        verify(newRepository, times(1)).save(demoCaptor.capture());
        final Demo actual = captor.getValue();
        final Demo expected = //create your expected here
        assertEquals(expected, actual);
    }

Remember to implement equals() and hashCode() in your Demo class, or another option could be asserting on the fields of Demo you care about. I'm also not sure what cart on which you are calling getName() is, but if it's another dependency of your service you will have to inject it as a mock and properly set it up with when() and return value.

The differences in terms of junit4/5 should be (not 100% sure it's all of them, going with my memory here):

  • the imports
  • the @ExtendWith should be @RunWith(mockitojunitrunner.class)
  • the test for the exception should be @Test(expected = ApiError.class) instead of using assertThrows
burm87
  • 768
  • 4
  • 17
0

This function basically saves the data if the data is not available in the repository, Junits are meant to check if this function is working as expected. Here you will test for 2 cases

  1. when data is available in the repository: For this mock repository.existsByNameAndAge(...) and return false ,in test case use expected @Test(expected=ApiError.class)

  2. when it is not: In this case use opposite of the above case and don't use the expected attribute.