sonarqubesonarqube-scansonar-runnersonarlintsonarqube5.1

SonarQube doesn't recognize Mapper's unit test


Running SonarQube Version 6.7.2 (build 37468) - LGPL v3, Junit 4 and mockito in our project, I noted that SonarQube does not recognize Mapper's unit test and decrease the project's percentual. In my local enviroment, the test works well and the coverage is 100% by Eclipse.

Below is the UT code:

@RunWith(MockitoJUnitRunner.class)
public class ClassMapperTest {
    
    @Mock
    private ClassMapper mapper;
    
    @Mock
    private ClassDTO dto;
    
    @Before
    public void setUp() {
        mapper = Mockito.mock(ClassMapper.class);
        dto = Mockito.mock(ClassDTO.class);
    }
    
    @Test
    public void returnResource() {
        Mockito.when(mapper.fromMethod(Mockito.anySet())).thenReturn(new HashSet<>());

        mapper.fromMethod(new HashSet<ClassDTO>());
    
    }

The statistics:

enter image description here

After Commit:

enter image description here

Does anyone have any idea?


Solution

  • Sonarqube is right with the computation. You do have a major issue within your test, the code you seem to be testing is mocked aka you are not testing the actual code, but a fake of it.

    When you mock a class you create a dummy fake version of this class, which does not have any implementation (mapper = Mockito.mock(ClassMapper.class);). you then tell your mock to return a value when a method is called Mockito.when(mapper.fromMethod(Mockito.anySet())).thenReturn(new HashSet<>());. This way you are actually not testing your fromMethod, you just testing a method, which you told in your test what to return.

    A proper test would look something like this:

    @RunWith(MockitoJUnitRunner.class)
    public class ClassMapperTest {
        
        private ClassMapper mapper;
        
        @Mock
        private ClassDTO dto;
        
        @Before
        public void setUp() {
            mapper = new ClassMapper();
            // no need to do that, MockitoJUnitRunner is doing this for you
            // dto = Mockito.mock(ClassDTO.class);
        }
        
        @Test
        public void returnResource() {
            // calling the actual method
            assertTrue(mapper.fromMethod(new HashSet<ClassDTO>()) != null);
        }
    }
    

    There is also no need for the dto as it is not used within your test at all, but I left it in there, to mark the unnecessary mock instantiation, which is done by the MockitoJUnitRunner.

    // Disclaimer: I am not guaranteeing that your tests will pass, with my suggestion, I only want to highlight the problem with the test.