@PostContruct method does not work with Mockito

Viewed 37

Hi I am trying to initialize a field with @PostConstruct method but in tests, this method does not fill the bidiMap field.

Is there any way to mock bidiMap field which is a field of DataSource ?

@Component
@Getter
@Setter
@NoArgsConstructor
public class DataSource {

    public DualHashBidiMap<String, String> bidiMap = new DualHashBidiMap();

    @PostConstruct
    public void loadData() throws IOException {
        Map<String, String> data = new ObjectMapper().readValue(new File("src/main/resources/static/data.json"), Map.class);
        data.entrySet().stream().forEach(item -> this.bidiMap.put(item.getKey(), item.getValue()));
    }
}

Test:

@Test
    void shouldReturnPrettifiedUrl_WithQueryParams() throws IOException {
        // Given
        List<String> inputParameters = Arrays.asList("/products?gender=female&tag=123&tag=1234");
        HashMap<String, String> expectedResult = PrettyUrlResponseBuilder.PrettyUrlResponseBuilder().createPrettyUrlResponseWithParams();
        HashMap<String, String> databaseResponse = DatabaseResponse.DatabaseResponse().createDatabaseResponse();
        System.out.println(dataSource);
        // When
        Map<String, String> actualResult = prettyUrlService.toPretty(inputParameters);

        // Then
        assertEquals(expectedResult, actualResult);
    }

The class being tested:

@Service
public class PrettyUrlService {
    private final DataSource dataSource;

    public PrettyUrlService(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Map<String, String> toPretty(List<String> urlList) throws IOException {
        var data = dataSource.getBidiMap(); // Here, data is null.
        // ...
    }
}
1 Answers

If you're unit testing the PrettyUrlService class then you should not need to also test the underlying DataSource class within the same test. Simply mocking the DataSource interactions and verifying that all the expected interactions are happening should be more than enough.

E.g. (assuming JUnit 5):

@ExtendWith(MockitoExtension.class)
class PrettyUrlServiceTest {

  @Mock
  private DataSource dataSource;
  private PrettyUrlService prettyUrlService;

  @BeforeEach
  void setUp() {
    prettyUrlService = new PrettyUrlService(dataSource);
  }

  @Test
  void exampleTest() {
    DualHashBidiMap<String, String> bidiMap = new DualHashBidiMap();
    // add test data to the map
    bidiMap.put("testKey", "testValue"); // replace with data you need for test
    Mockito.when(dataSource.getBidiMap()).thenReturn(bidiMap);
    
    // insert test logic here (prettyServiceUrl call + assertions)
    // ...

    // finally, verify that dataSource.getBidiMap() was called exactly once
    Mockito.verify(dataSource).getBidiMap();
  }

}
Related