logoalt Hacker News

MadVikingGodyesterday at 4:05 PM4 repliesview on HN

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...

Replies

metadatyesterday at 5:03 PM

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.*

show 1 reply
matttproudyesterday at 5:25 PM

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

show 1 reply
awesome_dudeyesterday at 9:08 PM

Just for the record - this is package local - it's fine within the package it is defined in, but no other package will use the implementation, they will all use the standard library.

Others have linked to the much more "fun" https://github.com/bouk/monkey which is an actual monkey patch, in that it changes the code that is called from anywhere in the runtime

antonvsyesterday at 4:24 PM

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.

show 1 reply