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:
- Fake objects
- 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());
}