Remix.run Logo
MadVikingGod 3 hours ago

This is all possible and quite neat to dive into the specifics, but if you really want to be able swap a std lib call, just turn it into a variable and change it.

  // code.go
  var now = time.Now

  // code_test.go
  func TestCode(t *testing.T) {
      nowSwap := now
      t.Cleanup (func() {
          now = nowSwap
      }
      now = func() time.Time {
          return time.Date(...)
      }
  }

Examples Code: https://github.com/open-telemetry/opentelemetry-go/blob/main... Test: https://github.com/open-telemetry/opentelemetry-go/blob/490f...
matttproud an hour ago | parent | next [-]

This is often the path of pain: https://google.github.io/styleguide/go/best-practices#global....

metadat 2 hours ago | parent | prev | next [-]

That is a useful pattern, though I was unclear on why `t.Cleanup` and not `defer`. In case others are curious, too:

> Parallel subtestsWith t.Run(..., func(t testing.T) { t.Parallel(); ... }), the parent test function can return (and thus run its defers) before parallel subtests actually finish.*

antonvs 2 hours ago | parent | prev [-]

The point of the OP is that it changes calls to `time.Now` regardless of whether the code that's calling it uses your variable or not.

Groxx 2 hours ago | parent [-]

I suspect that using a build tag (say `test`) and two function definitions (one that directly calls `time.Now()` and one test-only one that uses a mutable var) will optimize out to zero cost in the non-test case - last I fiddled with that, it was pretty good at consistently inlining trivial wrapper funcs like that.