Mock Projection Result Spring Data JPA

Viewed 10464

I am using spring data jpa in my spring boot project.

I am firing an JPQL query and using an projection to store the result of query. My Projection :

public interface VeryBasicProjection {
    String getTitle();
    String getUrl();
}

My service calling this projection :

public List<VeryBasicDTO> getLatestData(int limit){

        // Pageable for Limit
        Pageable pageable = new PageRequest(0, limit);

        // Get Data from DB
        List<VeryBasicProjection> latestData = tableRepository.getLatestData("live", 2,pageable);
        List<VeryBasicDTO> responseDTO = new ArrayList<>();

        // Map Projection to DTO
        for(VeryBasicProjection veryBasicProjection : latestData){
            VeryBasicDTO veryBasicDTO = new VeryBasicDTO();
            veryBasicDTO.buildDTO(veryBasicProjection);
            responseDTO.add(veryBasicDTO);
        }

        return responseDTO;
    }

Now i want to test this service using Mockito(Unit Test Case) I am mocking the call to repository using when and thenReturn.

My question is how do I mock the result of repository? What should be in thenReturn? I mean how do I create instance of projection and setData to it?

5 Answers

If you want to create an instance of your projection without creating a class implementing the interface, you can use SpelAwareProxyProjectionFactory.

import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;

...
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
VeryBasicProjection projection = factory.createProjection(VeryBasicProjection.class);
projection.setTitle("theTitle");
projection.setUrl("theUrl");

You also need to add setters in your projection:

public interface VeryBasicProjection {
    String getTitle();
    String getUrl();
    void setTitle(String title);
    void setUrl(String url);
}

Source: https://github.com/spring-projects/spring-data-examples/blob/master/rest/projections/src/test/java/example/springdata/rest/projections/SimpleProjectionTests.java

This is the simplest way to mock projections in TEST

VeryBasicProjection VeryBasicProjection = new VeryBasicProjection() {
   String getTitle() {
    return "Title";
   }

    String getUrl() {
      return "url";
    }
}

As an addition to Nis' answer:

If the interface doesn't have setters, the projection can be initialized with a map:

ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
Map<String, Object> map = Map.of("title", "theTitle", "url", "theUrl");
VeryBasicProjection projection = factory.createProjection(VeryBasicProjection.class, map);

We have implemented the same stuff in below way

First mocked the two type of objects:

@Mock
private EntityManager em;

@Mock
private DemoProjectRepo demoProjectRepo;

My demoProjectRepo.findByAll returns List<DemoProjectDevices>

DemoProjectDevices device1 = new DemoProjectDevices();
device1.setAcctNbr("2365897412236589");
device1.setdeviceSeq(new BigDecimal(1));
device1.setCrteTms("2017-07-29 01:21:44.910807");
List<DemoProjectDevices> demoProjectDevices = new ArrayList<DemoProjectDevices>();
demoProjectDevices.add(device1);

For the mock when and then:

Mockito.when(demoProjectRepo.findByAll("2365897412236589", em)).thenReturn(demoProjectDevices);

In your projection interface you need to add setters for the values you have getters for.

So when you have a concrete class implementing the projection interface you can add the values to that class so you might have something along these lines:

    public interface VeryBasicProjection {
        String getTitle();
        String getUrl();
        void setTitle(String title);
        void setUrl(String url);
    }

    public class VeryBasicProjectionImpl implements VeryBasicProjection{
        //add implementing methods
    }

    ////

    @Mock
    Repository tableRepo;

    @InjectMocks
    ClassUnderTest c;

    @Test
    public void test(){

        // Pageable for Limit
        Pageable pageable = new PageRequest(0, limit);

        VeryBasicProjection vbp = new VeryBasicProjectionImpl();
        // add data to object here using the setters

        List<VeryBasicProjection> projList = new ArrayList<>()
        //add objects created

        when(tableRepo.getLatestData("live", 2, pageable)).thenReturn(projList));

    }
Related