3

I have a spring based project and I am trying to improve the code coverage within it

I have the following block of code which uses a lambda on the defferedResult onCompletion method

        util.getResponse(userInfoDeferredResult, url, userName, password);

    userInfoDeferredResult.onCompletion(() -> {
        //the result can be a String or ErrorResponse
        //if ErrorResponse we don't want to cause ClassCastException and we don't need to cache the result
        if (userInfoDeferredResult.getResult() instanceof String){

            String response = (String) userInfoDeferredResult.getResult();

            cacheServices.addValueToCache(Service.USER_INFO_CACHE_NAME, corpId, response);              
        }
    });

I was wondering - is it possible to mock the contents of the onCompletion lambda using mockito or powerMockito?

Damien
  • 4,081
  • 12
  • 75
  • 126

4 Answers4

6

Extract contents to new method:

if(userInfoDeferredResult.getResult() instanceof String) {
     String response = (String) userInfoDeferredResult.getResult();
     cacheServices.addValueToCache(Service.USER_INFO_CACHE_NAME, corpId, response);              
 }

Then test the method that way?

Nigam Patro
  • 2,760
  • 1
  • 18
  • 33
Cowboy Farnz
  • 329
  • 2
  • 11
  • Yeah I was hoping to not have to do that. I would like to get a solution that is lambda friendly but this is a good approach if there are no alternatives – Damien Nov 24 '17 at 11:21
4

Your test should rather mock cacheServices, and execute the lambda.

tkruse
  • 10,222
  • 7
  • 53
  • 80
2

Extracting contents to new method is good solution in this case as mentioned in other answer.

Also, you can find article about in the following link: http://radar.oreilly.com/2014/12/unit-testing-java-8-lambda-expressions-and-streams.html

Furkan Yavuz
  • 1,858
  • 5
  • 30
  • 51
1

Generally I prefer not to change the service code for test code (for example extracting to method and make it public although it should be private). The onCompletion method is triggered when the completed of AsyncContext is called. So you can test in the following way:

@RunWith(SpringRunner.class)
@WebMvcTest(DeferredResultController.class)
public class DeferredResultControllerUnitTest {

    @MockBean
    CacheServices cacheServices;

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void onCompletionTest() throws Exception {
        mockMvc.perform(get("/your_url"))
                .andDo(mvcResult -> mvcResult.getRequest().getAsyncContext().complete());
        Mockito.verify(cacheServices)
               .addValueToCache(Service.USER_INFO_CACHE_NAME, getExpextedCorpId(), getExpectedResponse());
        }
    }

Working github example here.

In contrast to @SpringBootTest, @WebMvcTest won't start the all Spring application context so it is more lighter.

elirandav
  • 1,913
  • 19
  • 27