1

I am trying to change the behavior of the System.currentTimeMillis() method for testing purposes. I found the method below, but I can not use the aspect keyword in code. I do not really understand how this method can be used. Any suggestions?

public aspect CurrentTimeInMillisMethodCallChanger {
    long around():
        call(public static native long java.lang.System.currentTimeMillis()) 
               && within(user.code.base.pckg.*) {
            return 0; // provide your own implementation returning a long
        }
}

See the related answer containing the source of the above code for more details

Nándor Előd Fekete
  • 6,988
  • 1
  • 22
  • 47
Dinu Nicolae
  • 1,019
  • 2
  • 17
  • 42
  • This piece of code relies on [AspectJ](https://www.eclipse.org/aspectj/), a Java library for Aspect Oriented Programming (Baeldung has a [good introduction to it](https://www.baeldung.com/aspectj)). It's a bit overkill for the sole purpose of mocking a static method so I wouldn't recommend it in your case. – Emmanuel Chebbi May 26 '20 at 09:18
  • This method should work with AspectJ, both load-time and compile-time weaving. Instead of only quoting the other answer you should have explained what you tried and what is not working. Have you read an AspectJ introduction? As it is, the question is unclear, which is why you got two close votes already. You ought to improve it. – kriegaex May 27 '20 at 08:39
  • @kriegaex I guess this is not a very good question indeed. How to close it? – Dinu Nicolae May 27 '20 at 16:03
  • 1
    To the people who voted that this is a duplicate: I don't think so, because the question was about AspectJ, not about PowerMock(ito). And even if you use PowerMock, please note that `System.currentTimeMillis()` is a **native** method, i.e. it cannot be mocked directly by byte code modification. The only thing possible is to instrument the code in all places where the method is called (which PowerMock can also do, I know). This is also why it works with AspectJ, using `call()` pointcut, not `execution()`. – kriegaex May 28 '20 at 04:08

1 Answers1

7

Don't. Don't use System.currentTimeMillis() in your code if you need to test with specific times, use a Clock instead:

The primary purpose of this abstraction is to allow alternate clocks to be plugged in as and when required. Applications use an object to obtain the current time rather than a static method. This can simplify testing.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • The problem is I have a quit complex integration test and I can not mock the object that uses the System.currentTimeMillis() method. If I would use a clock, I could still not change it. – Dinu Nicolae May 26 '20 at 09:21
  • @DinuNicolae if you can't fix the time, you have to change your tests to use the actual time. This makes them harder to write and less reproducible. Designing code for testability is important. – Andy Turner May 26 '20 at 09:39
  • I guess you are right that the tests are not very well design. – Dinu Nicolae May 26 '20 at 09:41