Skip to content

Clock Module

ci go report codecov Deps PkgGoDev

Overview

Yokai provides a fxclock module, that you can use to control time.

It wraps the clockwork module.

Installation

First install the module:

go get github.com/ankorstore/yokai/fxclock

Then activate it in your application bootstrapper:

internal/bootstrap.go
package internal

import (
    "github.com/ankorstore/yokai/fxcore"
    "github.com/ankorstore/yokai/fxclock"
)

var Bootstrapper = fxcore.NewBootstrapper().WithOptions(
    // modules registration
    fxclock.FxClockModule,
    // ...
)

Usage

This module provides a clockwork.Clock instance, ready to inject in your code.

This is particularly useful if you need to control time (set time, fast-forward, ...).

For example:

internal/service/example.go
package service

import (
    "github.com/jonboulle/clockwork"
)

type ExampleService struct {
    clock clockwork.Clock
}

func NewExampleService(clock clockwork.Clock) *ExampleService {
    return &ExampleService{
        clock: clock,
    }
}

func (s *ExampleService) Now() string {
    return s.clock.Now().String()
}

See the underlying vendor documentation for more details.

Testing

This module provides a *clockwork.FakeClock instance, that will be automatically injected as clockwork.Clock in your constructors in test mode.

Global time

By default, the fake clock is set to time.Now() (your test execution time).

You can configure the global time in your test in your testing configuration file (for all your tests), in RFC3339 format:

configs/config_test.yaml
modules:
  clock:
    test:
      time: "2006-01-02T15:04:05Z07:00" # time in RFC3339 format

You can also override this value, per test, by setting the MODULES_CLOCK_TEST_TIME env var.

Time control

You can populate the *clockwork.FakeClock from your test to control time:

internal/service/example_test.go
package service_test

import (
    "testing"
    "time"

    "github.com/ankorstore/yokai/fxsql"
    "github.com/foo/bar/internal"
    "github.com/foo/bar/internal/service"
    "github.com/jonboulle/clockwork"
    "github.com/stretchr/testify/assert"
    "go.uber.org/fx"
)

func TestExampleService(t *testing.T) {
    testTime := "2025-03-30T12:00:00Z"
    expectedTime, err := time.Parse(time.RFC3339, testTime)
    assert.NoError(t, err)

    t.Setenv("MODULES_CLOCK_TEST_TIME", testTime)

    var svc service.ExampleService
    var clock *clockwork.FakeClock

    internal.RunTest(t, fx.Populate(&svc, &clock))

    // current time as configured above
    assert.Equal(t, expectedTime, svc.Now()) // 2025-03-30T12:00:00Z

    clock.Advance(5 * time.Hour)

    // current time is now advanced by 5 hours
    assert.Equal(t, expectedTime.Add(5*time.Hour), svc.Now()) // 2025-03-30T17:00:00Z
}

See tests example for more details.