0

I have a private method getListSonarMetricsFromRegistry declared in the Class SonarRestApiServiceImpl that I want to call, with Java reflection, but I get the exception:

java.lang.NoSuchMethodException: com.cma.kpibatch.rest.impl.SonarRestApiServiceImpl.getListSonarMetricsFromRegistry(java.util.HashMap)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at com.test.service.rest.SonarRestApiServiceImplTest.testGetListSonarMetricsFromRegistry(SonarRestApiServiceImplTest.java:81)


I tried to use Java reflection, like below :

    @Test
    public void initTest() throws NoSuchMethodException, SecurityException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {
        Map<Long, KpiMetric> tmp = new HashMap<>();
        Method method = sonarRestApi.getClass().getDeclaredMethod("getListSonarMetricsFromRegistry", tmp.getClass());
        method.setAccessible(true);
        List<String> list = (List<String>) method.invoke(sonarRestApi, registry.getKpiMetricMap());
    }

Here is the getListSonarMetricsFromRegistry method declaration:

//This method works correctly, it returns a List of String without error
private List<String> getListSonarMetricsFromRegistry(Map<Long, KpiMetric> map) {
    return //something
}

When I look at the Exception, the trace print my Class with the right package, right name, right method name and right parameters:

com.test.rest.impl.SonarRestApiServiceImpl.getListSonarMetricsFromRegistry(java.util.HashMap) But it say that this method does not exist, which is strange.

The similar questions provided by Stackoverflow did help, but I still have the same Exception.

1
  • 4
    HashMap is not the same as Map - one is the interface the other the implementation. Your call to getDeclaredMethod uses tmp.getClass which will return HasMap.class and your method takes a Map. You need to call with Map.class. Commented Aug 27, 2019 at 10:02

1 Answer 1

1

I think your problem is that you give a HashMap class instance as an argument to getDeclaredMethod while the method actually accepts Map class instance. Remember, that all generic arguments are stripped out on compilation, so a Map<Whatever,WhateverElse> simply becomes a Map when doing reflection at runtime. So try:

 Method method = sonarRestApi.getClass().getDeclaredMethod("getListSonarMetricsFromRegistry", Map.class);

On a related note, basing tests on reflectively calling private API is probably not a good way to keep tests maintainable in the long run. I'm not sure why you would need to do this trickery, but if you can, try to find a way that works with public API.

Sign up to request clarification or add additional context in comments.

1 Comment

Indeed that solve the issue, you are also right about what I am doing, being a trick, I'll see if I can find another way of doing, thanks for the help

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.