0

I want to mock the update method and I want to check if it returns false in validate method when the time is false. so I tried mocking call to LocalDateTime.now() method. It works if I directly call timeValidator.validate() but when I call service.update() it gives a new object of LocalDateTime, maybe because it is nested in 3 levels it is not passing the mocked object.

The string to TimeValidator constructor is like "20:00". So what this program is supposed to do is if I the activity is to eat and for that time limit is "22:00" then it validator should return false if the current time is after 10 PM. Sample code is like below:

   //Service
public class ServiceImpl{
    //all other methods    
    public void update(){
      //other code
      List<Validator> validators = new ArrayList<>();
      validators.add(new TimeValidator(timeString);
      //other validators
      Activity activity = new Activity(userId, validators);
      activity.execute();
    }
}

//Activity Class
public class Activity{

    //other methods

       public void execute(){
           for(v : validators){
               if(!v.validate()){
                   throw MyException();
               }
           }
       }
}


//TimeValidator class
TimeValidator implements Validator{
    public TimeValidator(String timeString){
        //some code
    }
    public boolean validate(){
        LocalDateTime currentTime = LocalDateTime.now();
        LocalDateTime cutOffTime = LocalDateTime.of(LocalDateTime.now(), LocalDateTime.parse(timeString));
        return currentTime.isBefore(cutOffTime);
    }
}

//Test class
@RunWith(PowerMockRunner.class)
@PrepareForTest(LocalDateTime.class)
public TestClass{

    @Test(expected = MyException.class)
    public void testUpdate(){
        //other code to get real object of service

        LocalDateTime currentTime = LocalDateTime.of(2018,01,02,22,15);
        PowerMockito.mockStatic(LocalDateTime.class);
        when(LocalDateTime.now()).thenReturn(currentTime);

        //assertFalse(timeValidator.validate());

        service.update();
    }

}
smurfette
  • 1
  • 1
  • 2
    Don't use `LocalDateTime.now()`: inject a `Supplier` into your `TimeValidator` class. Then you don't even need to mock it. – Andy Turner Jan 13 '18 at 22:00
  • Or use the `Clock` interface https://stackoverflow.com/questions/27067049/unit-testing-a-class-with-a-java-8-clock – David Rawson Jan 13 '18 at 22:04
  • I can't inject or change the type. I have to use LocalDateTime. That's the requirement. – smurfette Jan 14 '18 at 00:57
  • > "That's the requirement." From who? You're writing the code, why'd you allow someone else force you to write s*itty code? – Abhijit Sarkar Jan 14 '18 at 01:59
  • I don't think the problem is because of how I create object or where I pass it from. I think it is because the test method has the currentTime object which I want in validate method and the call goes from update() to execute() to validate() and PowerMockito is not able to pass it 3 different calls. If in test method I call validate() or execute(), it works just fine. – smurfette Jan 14 '18 at 07:42
  • Is it possible to use something else in place of PowerMockito? – smurfette Jan 14 '18 at 23:52

0 Answers0