1

I need to mock the two static methods LocalDate.now() and LocalTime.now() in a testing class.

I'm using PowerMock but I receive this error when I try to run the test:

org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.client.RestTemplate]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: Could not initialize class javax.xml.transform.FactoryFinder

I had try to create a @Bean of RestTemplate.class inside the test class and configuration class but the error persists.

I have this error only if I run the test with PowerMockRunner.class. If I try to run it with SpringRunner.class everything is fine but I can't mock the LocalDate and LocalTime.

This is my Test class:

@PrepareForTest(LocalDate.class)
@RunWith(PowerMockRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = ChallengeApplication.class)
@ActiveProfiles("test")
public class MockTest {

    @Autowired
    private TestRestTemplate restTemplate;
    private URL base;

    @LocalServerPort
    int port;

    User user = new User("user", "password", "user@test.com");
    HttpEntity<User> userRequest = new HttpEntity<>(user);

    Mock mock = new Mock(new BigDecimal(20));
    HttpEntity<Mock> request = new HttpEntity<>(mock );

    @Before
    public void setUp() throws MalformedURLException {
        restTemplate = new TestRestTemplate();
        base = new URL("http://localhost:" + port + "/mock/users");
        restTemplate.postForEntity(base.toString(), userRequest, String.class);

        restTemplate = new TestRestTemplate(user.getUsername(), user.getPassword());
        base = new URL("http://localhost:" + port + "/mock/mocks");
    }

    @Test
    public void wrongUserAuth_ThenFailed() throws IllegalStateException {
        restTemplate = new TestRestTemplate("test", "test");
        ResponseEntity<String> response = restTemplate.postForEntity(base.toString(), request, String.class);

        assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
    }

    @Test
    public void createTwoAccountsForTheSameUser_ThenFailed() throws IllegalStateException {
        restTemplate.postForEntity(base.toString(), request, String.class);
        ResponseEntity<String> responseTwo = restTemplate.postForEntity(base.toString(), request, String.class);

        assertEquals(HttpStatus.CONFLICT, responseTwo.getStatusCode());
        assertTrue(responseTwo
            .getBody()
            .contains("mock"));
    }

    @Test
    public void createAccountDuringWeekend_ThenFailed() throws IllegalStateException {
        LocalDate date = LocalDate.of(2000, 1, 1);
        PowerMockito.stub(PowerMockito.method(LocalDate.class,"now")).toReturn(date);
        ResponseEntity<String> response = restTemplate.postForEntity(base.toString(), request, String.class);

        assertEquals(HttpStatus.CONFLICT, response.getStatusCode());
        assertTrue(response
                .getBody()
                .contains("mock"));
    }
}
liviubiur
  • 111
  • 3
  • 13
  • Why would you need to mock those? I doubt it is possible without much trickery (generally when going down this path, mocking java classes or statics, something is wrong in your design IMHO). – M. Deinum Jul 09 '20 at 12:24
  • I need to mock it because I want to return a different day then LocalDate.now(). For example when I call in my implementantion LocaDate.now(), instead to return 09.07.2020, I wan to return 05.02.2020. – liviubiur Jul 09 '20 at 12:27
  • This is a little confusing written. The problem does not seem to be the mocking of LocalDate.now() (or in general: a static method); the problem is that introducing powermock causes your tests to fail because of the mentioned class initialization error. – Gimby Jul 09 '20 at 12:46
  • Indeed, that seems to be the issue and actually I don't understand why and what is the root of it. – liviubiur Jul 09 '20 at 12:51
  • 1
    Introduce a clock, and for test use a static one, and use the `now` method that uses a `java.time.Clock`. No need to mock that. – M. Deinum Jul 09 '20 at 12:52
  • I tried to use this implementation: https://stackoverflow.com/questions/32792000/how-can-i-mock-java-time-localdate-now . I put the `@Bean public Clock clock() { return Clock.systemDefaultZone(); }` inside the SpringBootApplication and wired to my Service and to my Test. I tried to debug it and I saw that when the call arrives at the Service, it call the current day instead of the one which I created inside the Test. – liviubiur Jul 09 '20 at 12:59
  • The last comment sounds to me like a wiring problem that you can solve more easily than you can mock those methods. See also [Writing and testing convenience methods using Java 8 Date/Time classes](https://stackoverflow.com/questions/52956373/writing-and-testing-convenience-methods-using-java-8-date-time-classes). – Ole V.V. Jul 09 '20 at 19:46

0 Answers0