Logo

Testing scheduled jobs using faketime

Recently, I was tasked with testing some scheduled exports to investigate a defect. Unit tests should have caught it, but something else was going on. I had to simulate a real execution in a container by faking its internal clock.

This is where I utilized faketime.

faketime is a tool that manipulates system time for a specific program without changing the system's actual time. It works by intercepting the system calls a program makes to get the current date and time, allowing you to run programs as if it were a different date and time.

Check for the faketime package

First, you need to make sure the faketime package is available in your container image, as it's not commonly included. To confirm that the library file exists, you can run:

podman exec -it {container_name} find / -name libfaketime.so.1

If that command finds the library file (e.g., at /usr/lib/faketime/libfaketime.so.1), you're good to go. Otherwise, you'll have to install it.

Usage

So how do you use it? It's actually pretty simple.

podman exec -it {container_name} sh -c "LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 FAKETIME_NO_CACHE=1 FAKETIME=\"$(date -u -d '30 days ago' '+%Y-%m-%d 00:01:00')\" php artisan schedule:work"

What's being passed here are:

  • LD_PRELOAD=...: This tells the shell to load the faketime library before running the command.
  • FAKETIME_NO_CACHE=1: This prevents the time from being cached, which is important for testing.
  • FAKETIME="...": This sets the exact time you want to simulate. In this case, I'm using date to get a formatted string for "30 days ago at 1:00 AM UTC."
  • php artisan schedule:work: This is the actual command I wanted to test (a Laravel scheduler, in this case).

Since I was testing an export, I had to make sure it worked on a daily, monthly, and yearly basis. Using this command, I could just change the date string to simulate any scenario. This was a really interesting and effective way to test.