Home > Software design >  How to deal with Page while unit testing with mockito and Junit
How to deal with Page while unit testing with mockito and Junit

Time:12-13

I want to mock database call with fake data but I got stuck in the following scenario:

MyService

public class MyService {
    // some stuff

    Page<SampleDto> sample = repo.findAllSample();

    // other stuff
}

I want to stub this with when() but I am not able to do this. My test is: MyServiceTest

public class MySampleTest {

    @Test
    void myTest() {
        // initialisation and all stuff

        when(myRepo.findAll()).thenReturn(......)
        // I want to pass 2 fake SampleDto from 
        // here but don't know how to do that
    }
}

CodePudding user response:

Just create what you want to be returned and pass it to thenReturn().

In your case it could look like this:

// I making this up, because you did not state what 'Page' actually is
var result = new Page();
result.add(new SampleDto(1));
result.add(new SampleDto(2));
when(myRepo.findAllSample()).thenReturn(result);

You might not be able to do this, depending on the actual implementation of Page, for instance if this is a JPA Page. In this case you should not really return Page into your Service anyway, but wrap the JPA repository into a adapter repository that returns a List<SampleDto> or Set<SampleDto> instead. Otherwise your Service, which belongs to the Domain, would depend on an implementation detail of infrastructure code like JPA, which is rarely a good idea.

CodePudding user response:

Usually there are two main directions for resolving such types of tasks:

  1. Fake objects
  2. Mocking

Fake objects approach is plain implementation of your repo without any third-party libs for lightweight/simple cases:

public class FakeRepo implements Repo<T> {
   private final Collection<T> all;

   public FakeRepo(){
      this(Collections.emptySet());
   }

   public FakeRepo(Collection<T> all){
       this.all = all;
   }

   @Override
   public Collection<T> findAll(){
       return this.all;
   }
}

and in your test may looks like

@Test
public void justdoit(){
   MyService service = new MyService(
       new FakeRepo(Arrays.asList(1,2))
   );
   // test the service & methods
}

Mocking allows you to make much more complex solutions. Please make attention on methods Mockito.mock(ArrayList.class) and Mockito.spy(new ArrayList<String>()). You need to assemble your complex objects using Mockito engine like https://www.baeldung.com/mockito-annotations

@Test
public void whenNotUseMockAnnotation_thenCorrect() {
    List mockList = Mockito.mock(ArrayList.class);
    
    mockList.add("one");
    Mockito.verify(mockList).add("one");
    assertEquals(0, mockList.size());

    Mockito.when(mockList.size()).thenReturn(100);
    assertEquals(100, mockList.size());
}

or

@Test
public void whenNotUseSpyAnnotation_thenCorrect() {
    List<String> spyList = Mockito.spy(new ArrayList<String>());
    
    spyList.add("one");
    spyList.add("two");

    Mockito.verify(spyList).add("one");
    Mockito.verify(spyList).add("two");

    assertEquals(2, spyList.size());

    Mockito.doReturn(100).when(spyList).size();
    assertEquals(100, spyList.size());
}

CodePudding user response:

You can mock the Page object also if there is a aneed to handle some other functionality inside your service class. Assuming that your service class is actually something like:

public class MyService {
    @Resource
    private SampleRepository repo;

    public Page<SampleDto> findAllSample() {
        var sampleData = repo.findAllSample();
        // perhaps some operations with sample data and page
        return sampleData;
    }
}

then the test class could be something like (JUnit4):

@RunWith(MockitoJUnitRunner.class)
public class MySampleTest {
    @Mock
    private SampleRepository repo;
    @Mock
    private Page<SampleDto> page;
    @InjectMocks
    private MyService myService;

    @Test
    public void test() {
    doReturn(page).when(repo).findAll();
    var listSampleDtos = List.of(new SampleDto()); // populate with what you need
    doReturn(listSampleDtos).when(page).getContent();
    var page = myService.findAllSample();
    // ... do the asserts, just as an example:
    verify(repo).findAll(); // called
    assertEquals(1, page.getContent().size());
    }
  • Related