Go Lang How to Mock Package Method? [duplicate] - unit-testing

Part of our code is time-sensitive, and we need to able to reserve something and then release it in 30-60 seconds, etc., which we can just do a time.Sleep(60 * time.Second).
I have just implemented the time interface, and during the test I used a stubbed implementation of the time interface, similar to this golang-nuts discussion.
However, time.Now() is called in multiple sites which means we need to pass a variable around to keep track of how much time we have actually slept.
Is there an alternative way to stub out time.Now() globally? Maybe making a system call to change the system clock?
Can we maybe write our own time package which basically wraps around the time package but allows us to change it?
Our current implementation works well. I am a Go beginner, and I am curious to see if anyone has other ideas.

With implementing a custom interface you are already on the right way. I take it you use the following advise from the golang-nuts thread you've posted:
type Clock interface {
Now() time.Time
After(d time.Duration) <-chan time.Time
}
and provide a concrete implementation
type realClock struct{}
func (realClock) Now() time.Time { return time.Now() }
func (realClock) After(d time.Duration) <-chan time.Time { return time.After(d) }
and a testing implementation.
Original
Changing the system time while making tests (or in general) is a bad idea.
You don't know what depends on the system time while executing tests and you don't want to find out the hard way by spending days of debugging into that. Just don't do it.
There is also no way to shadow the time package globally and doing that would not do
anything more you couldn't do with the interface solution. You can write your own time package
which uses the standard library and provides a function to switch to a mock time library for
testing if it is the time object you need to pass around with the interface solution that is bothering you.
The best way to design and test your code would probably be to make as much code stateless as possible.
Split your functionality in testable, stateless parts. Testing these components separately is much easier then. Also, fewer side effects means that it is much easier to make the code run concurrently.

If the methods you need to mock are few, such as Now(), you can make a package variable which can be overwritten by tests:
package foo
import "time"
var now = time.Now
// The rest of your code...which calls now() instead of time.Now()
then in your test file:
package foo
import (
"testing"
"time"
)
var now = func() time.Time { return ... }
// Your tests

I use the bouk/monkey package to replace the time.Now() calls in my code with a fake:
package main
import (
"fmt"
"time"
"github.com/bouk/monkey"
)
func main() {
wayback := time.Date(1974, time.May, 19, 1, 2, 3, 4, time.UTC)
patch := monkey.Patch(time.Now, func() time.Time { return wayback })
defer patch.Unpatch()
fmt.Printf("It is now %s\n", time.Now())
}
This works well in tests to fake out system dependencies and avoids the abused dependency injection (DI) pattern. Production code stays separate from test code and you gain useful control of system dependencies.

Also if you need to just stub time.Now you can inject the dependency as a function, e.g.,
func moonPhase(now func() time.Time) {
if now == nil {
now = time.Now
}
// Use now()...
}
// Then dependent code uses just
moonPhase(nil)
// And tests inject own version
stubNow := func() time.Time { return time.Unix(1515151515, 0) }
moonPhase(stubNow)
Granted, all that is a bit ugly if you come from a dynamic languages background (e.g., Ruby) :(

There are multiple way to mock or stub time.Now() in test code:
Passing an instance of time to the function
func CheckEndOfMonth(now time.Time) {
...
}
Passing a generator to the function
CheckEndOfMonth(now func() time.Time) {
// ...
x := now()
}
Abstract with an interface
type Clock interface {
Now() time.Time
}
type realClock struct {}
func (realClock) Now() time.Time { return time.Now() }
func main() {
CheckEndOfMonth(realClock{})
}
Package level time generator function
type nowFuncT func() time.Time
var nowFunc nowFuncT
func TestCheckEndOfMonth(t *Testing.T) {
nowFunc = func() time.Time {
return time.Now()
}
defer function() {
nowFunc = time.Now
}
// Test your code here
}
Embed time generator in struct
type TimeValidator struct {
// .. your fields
clock func() time.Time
}
func (t TimeValidator) CheckEndOfMonth() {
x := t.now()
// ...
}
func (t TimeValidator) now() time.Time {
if t.clock == nil {
return time.Now() // default implementation which fall back to standard library
}
return t.clock()
}
Each has its own pluses and minuses. The best way is to separate the function that generates the time and the processing part that uses the time.
The post Stubbing Time in golang goes into details about it and there is an example for making function with time dependency to be easily tested.

We can stub time.Now simply by using the Go package undefinedlabs/go-mpatch.
Import the go-mpatch package and put the below code snippet in the code wherever you need to stub time.Now():
mpatch.PatchMethod(time.Now, func() time.Time {
return time.Date(2020, 11, 01, 00, 00, 00, 0, time.UTC)
})
Replace the values of time.Date as per your need.
check out the sample code to check the working of go-mpatch.
go-playground sample

I found a relatively simple solution here. The basic idea is using another function called "nowFunc" to get the time.Now().
In your main, initialize this function to return time.Now(). In your test, initialize this function to return a fixed fake time.

This is the same as Jonathan Hall's answer, but I am adding a concrete example.
Concept:
You can create a global function called CurrentTime to wrap the time.now()
Reassign the CurrentTime function in tests, and make it return the desired value.
File main.go
package main
import (
"fmt"
"time"
)
func main() {
fmt.Printf("This is the current year : %d ", GetCurrentYear())
}
// 'GetCurrentYear' function uses 'CurrentTime' function internally
func GetCurrentYear() int {
return CurrentTime().Year()
}
var CurrentTime = func() time.Time {
return time.Now()
}
File main_test.go
package main
import (
"testing"
"time"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) { TestingT(t) }
type S struct{}
var _ = Suite(&S{})
func (s *S) TestCurrentYearShouldBeReturnedCorrectly(c *C) {
expectedYear := 2022
curentInstant := time.Date(expectedYear, 12, 01, 00, 00, 00, 0, time.UTC)
// Make 'CurrentTime' return hard-coded time in tests
CurrentTime = func() time.Time {
return curentInstant
}
c.Assert(GetCurrentYear(), Equals, expectedYear)
}
Here is the Go Playground link.

The simple alternative is you can use sqlmock.AnyArg() to pass time.Now() as an argument.
Example
If the query is
[sqlBuilder.Update][2](tableName).Set("last_updated", time.Now()).Where(sq.Eq{"id": id}).ToSql()
and you want to mock this, do
sqlMock.ExpectExec("UPDATE tableName SET last_updated = ? WHERE id = ?").WithArgs(sqlmock.AnyArg())
instead of
sqlMock.ExpectExec("UPDATE tableName SET last_updated = ? WHERE id = ?").WithArgs(time.Now())

You can also use the faketime method used for Go Playground.
It will keep an internal "clock" value which replaces time.Now(), and will instantly return from any call to time.Sleep(), merely increasing the internal counter.
All calls to runtime.write (for example, fmt.Println) will be prefixed with the following header:
\0 \0 P B <8-byte time> <4-byte data length> (big endian)
It was implemented here: https://github.com/golang/go/commit/5ff38e476177ce9e67375bd010bea2e030f2fe19
Using it is as simple as go run -tags=faketime test.go
Example test.go:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("Test!")
time.Sleep(time.Second * 5)
fmt.Println("Done.")
}
Output:
go run -v -tags=faketime scratch_22.go | hexdump -C
00000000 00 00 50 42 11 74 ef ed ab 18 60 00 00 00 00 06 |..PB.t....`.....|
00000010 54 65 73 74 21 0a 00 00 50 42 11 74 ef ee d5 1e |Test!...PB.t....|
00000020 52 00 00 00 00 06 44 6f 6e 65 2e 0a |R.....Done..|
0000002c
However, I wouldn't recommend using this for actual unit tests, as the change to runtime.write will probably have unintended consequences, breaking a lot of other things.

What works for me is a small struct
package clock
import "time"
type Clock struct {
MockTime time.Time
}
func (c Clock) Now() time.Time {
if c.MockTime.IsZero() {
return time.Now() // use default golang
} else {
return c.MockTime
}
}
Embed the Clock struct in your struct as a dependency, or pass it along as function parameter.

Related

How should I test functions that deal with setting a large number of environment configs/OS arguments?

I've written a Go application, and all of the packages have full test coverage. I'm in the process of writing my main package - which will handle all of the initial setup for the application in the main() function - this function currently reads in 14 environment variables and then sets the relevant variable in the application. A simple overview of the code is:
func main() {
myStruct1 := privatePackage.myStructType{}
myStruct2 := publicPackage.otherStructType{}
if config1 := os.Getenv("CONFIG_FOO"); config1 != "" {
myStruct1.attribute1 = config1
}
// ....
if config14 := os.Getenv("CONFIG_BAR"); config14 != "" {
myStruct2.attribute5 = config14
}
}
When I test unit env variables/OS args, I typically just set the env variable directly in the test function - so something like:
func TestMyArgument(t *testing.T) {
os.Setenv("CONFIG_BAZ", "apple")
//Invoke function that depends on CONFIG_BAZ
//Assert that expected outcome occurred
}
I pretty much always use table-driven tests, so the above snippet is a simplified example.
The issue is that my main() function takes in 14 (and growing) env variables, and whilst some env variables are essentially enums (so there's a small number of valid options - for example there's a small number of database drivers to choose from), other env variables have virtually unlimited potential values. So how can I effectively cover all of the (or enough of the) permutations of potential configs?
EDIT: When this application is deployed, it's going into a K8s cluster. Some of these variables are secrets that will be pulled in from secure store. Using a JSON file isn't viable because some of the values need to be encrypted/changed easily.
Also, using a JSON file would require me to store this file and share it between hundreds/thousands of running pods - this storage would then act as a point of failure.
To clarify, this question isn't about env vars VS config files; this question is about the best way to approach testing when there's a significant number of configurable variables - with each variables having a vast number of potential values - resulting in thousands of possible configuration permutations. How do I guarantee sufficient test coverage in such a scenario?
#Steven Penny is right: uses json
and use reflect can make the code more simple:
package main
import (
"encoding/json"
"fmt"
"os"
"reflect"
"strconv"
)
type MyStructType struct {
Attribute1 string `json:"CONFIG_FOO"`
Attribute2 string `json:"CONFIG_BAZ"`
Attribute3 int `json:"CONFIG_BAR"`
}
func NewMyStructTypeFormEnv() *MyStructType {
myStructType := MyStructType{}
ReflectMyStructType(&myStructType)
fmt.Println("myStructType is now", myStructType)
return &myStructType
}
func NewMyStructTypeFormJson() *MyStructType {
myStructType := MyStructType{}
f, e := os.Open("file.json")
if e != nil {
panic(e)
}
defer f.Close()
json.NewDecoder(f).Decode(&myStructType)
fmt.Println("myStructType is now", myStructType)
return &myStructType
}
func ReflectMyStructType(ptr interface{}){
v := reflect.ValueOf(ptr).Elem()
fmt.Printf("%v\n", v.Type())
for i := 0; i < v.NumField(); i++ {
env_str := v.Type().Field(i).Tag.Get("json")
if(env_str == ""){continue}
if config := os.Getenv(env_str); config != "" {
if v.Field(i).Kind() == reflect.String{
v.Field(i).SetString(config)
}else if v.Field(i).Kind() == reflect.Int{
iConfig,_ := strconv.Atoi(config)
v.Field(i).SetInt(int64(iConfig))
}
}
}
}
func main() {
NewMyStructTypeFormJson()
os.Setenv("CONFIG_FOO", "apple")
os.Setenv("CONFIG_BAZ", "apple")
os.Setenv("CONFIG_BAR", "1")
NewMyStructTypeFormEnv()
}
Beyond one or two, I don't think using environment variables is the right approach, unless it's required (calling something with os/exec). Instead, would be better to read from a config file. Here is an example with JSON:
{
"CONFIG_BAR": "east",
"CONFIG_BAZ": "south",
"CONFIG_FOO": "north"
}
package main
import (
"encoding/json"
"fmt"
"os"
)
func main() {
f, e := os.Open("file.json")
if e != nil {
panic(e)
}
defer f.Close()
var s struct { CONFIG_BAR, CONFIG_BAZ, CONFIG_FOO string }
json.NewDecoder(f).Decode(&s)
// {CONFIG_BAR:east CONFIG_BAZ:south CONFIG_FOO:north}
fmt.Printf("%+v\n", s)
}
TOML would be a good choice as well.
https://golang.org/pkg/encoding/json
https://pkg.go.dev/github.com/pelletier/go-toml

How to test if a goroutine has been called while unit testing in Golang?

suppose that we have a method like this:
func method(intr MyInterface) {
go intr.exec()
}
In unit testing method, we want to assert that inter.exec has been called once and only once; so we can mock it with another mock struct in tests, which will give us functionality to check if it has been called or not:
type mockInterface struct{
CallCount int
}
func (m *mockInterface) exec() {
m.CallCount += 1
}
And in unit tests:
func TestMethod(t *testing.T) {
var mock mockInterface{}
method(mock)
if mock.CallCount != 1 {
t.Errorf("Expected exec to be called only once but it ran %d times", mock.CallCount)
}
}
Now, the problem is that since intr.exec is being called with go keyword, we can't be sure that when we reach our assertion in tests, it has been called or not.
Possible Solution 1:
Adding a channel to arguments of intr.exec may solve this: we could wait on receiving any object from it in tests, and after receiving an object from it then we could continue to assert it being called. This channel will be completely unused in production (non-test) codes.
This will work but it adds unnecessary complexity to non-test codes, and may make large codebases incomprehensible.
Possible Solution 2:
Adding a relatively small sleep to tests before assertion may give us some assurance that the goroutine will be called before sleep is finished:
func TestMethod(t *testing.T) {
var mock mockInterface{}
method(mock)
time.sleep(100 * time.Millisecond)
if mock.CallCount != 1 {
t.Errorf("Expected exec to be called only once but it ran %d times", mock.CallCount)
}
}
This will leave non-test codes as they are now.
The problem is that it will make tests slower, and will make them flaky, since they may break in some random circumstances.
Possible Solution 3:
Creating a utility function like this:
var Go = func(function func()) {
go function()
}
And rewrite method like this:
func method(intr MyInterface) {
Go(intr.exec())
}
In tests, we could change Go to this:
var Go = func(function func()) {
function()
}
So, when we're running tests, intr.exec will be called synchronously, and we can be sure that our mock method is called before assertion.
The only problem of this solution is that it's overriding a fundamental structure of golang, which is not right thing to do.
These are solutions that I could find, but non are satisfactory as far as I can see. What is best solution?
Use a sync.WaitGroup inside the mock
You can extend mockInterface to allow it to wait for the other goroutine to finish
type mockInterface struct{
wg sync.WaitGroup // create a wait group, this will allow you to block later
CallCount int
}
func (m *mockInterface) exec() {
m.wg.Done() // record the fact that you've got a call to exec
m.CallCount += 1
}
func (m *mockInterface) currentCount() int {
m.wg.Wait() // wait for all the call to happen. This will block until wg.Done() is called.
return m.CallCount
}
In the tests you can do:
mock := &mockInterface{}
mock.wg.Add(1) // set up the fact that you want it to block until Done is called once.
method(mock)
if mock.currentCount() != 1 { // this line with block
// trimmed
}
This test won't hang forever as with sync.WaitGroup solution proposed above. It will hang for a second (in this particular example) in case when there is no call to mock.exec:
package main
import (
"testing"
"time"
)
type mockInterface struct {
closeCh chan struct{}
}
func (m *mockInterface) exec() {
close(closeCh)
}
func TestMethod(t *testing.T) {
mock := mockInterface{
closeCh: make(chan struct{}),
}
method(mock)
select {
case <-closeCh:
case <-time.After(time.Second):
t.Fatalf("expected call to mock.exec method")
}
}
This is basically what mc.Wait(time.Second) in my answer above.
first of all I would use a mock generator, i.e. github.com/gojuno/minimock
instead of writing mocks yourself:
minimock -f example.go -i MyInterface -o my_interface_mock_test.go
then your test can look like this (btw the test stub is also generated with github.com/hexdigest/gounit)
func Test_method(t *testing.T) {
type args struct {
intr MyInterface
}
tests := []struct {
name string
args func(t minimock.Tester) args
}{
{
name: "check if exec is called",
args: func(t minimock.Tester) args {
return args{
intr: NewMyInterfaceMock(t).execMock.Return(),
}
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mc := minimock.NewController(t)
defer mc.Wait(time.Second)
tArgs := tt.args(mc)
method(tArgs.intr)
})
}
}
In this test
defer mc.Wait(time.Second)
Waits for all mocked methods to be called.

comparing current time in unit test

I'm currently writing a unit test that compares to strings. The first string is generated using a function. The other one is hard coded and serves as reference. My problem is, that the function creating the first string injects the current time (time.Now()) with precision in seconds into the string. At the moment I do the same for the reference but this seems very ugly to me. My machine runs fast enough so that the test passes but I don't want to rely on that.
What are general techniques to do such tests?
You can stub functions like time.Now() in your _test.go files, via the init() function, this will give deterministic time values:
package main
import (
"fmt"
"time"
)
var timeNow = time.Now
func main() {
fmt.Println(timeNow())
}
func init() {
// Uncomment and add to _test.go init()
// timeNow = func() time.Time {
// t, _ := time.Parse("2006-01-02 15:04:05", "2017-01-20 01:02:03")
// return t
// }
}
See: https://play.golang.org/p/hI6MrQGyDA
we can stub time.Now() by using go package "github.com/tkuchiki/faketime".
package main
import (
"fmt"
"github.com/tkuchiki/faketime"
"time"
)
func main() {
fmt.Println("Current Time Before Faking : ", time.Now().UTC())
f := faketime.NewFaketime(2021, time.March, 01, 01, 01, 01, 0, time.UTC)
defer f.Undo()
f.Do()
fmt.Println("Current Time After Faking : ", time.Now())
}
Output from the above code is :
Current Time Before Faking : 2009-11-10 23:00:00 +0000 UTC
Current Time After Faking : 2021-03-01 01:01:01 +0000 UTC
checkout the sample code : go-playground sample

Testing os.Exit scenarios in Go with coverage information (coveralls.io/Goveralls)

This question: How to test os.exit scenarios in Go (and the highest voted answer therein) sets out how to test os.Exit() scenarios within go. As os.Exit() cannot easily be intercepted, the method used is to reinvoke the binary and check the exit value. This method is described at slide 23 on this presentation by Andrew Gerrand (one of the core members of the Go team); the code is very simple and is reproduced in full below.
The relevant test and main files look like this (note that this pair of files alone is an MVCE):
package foo
import (
"os"
"os/exec"
"testing"
)
func TestCrasher(t *testing.T) {
if os.Getenv("BE_CRASHER") == "1" {
Crasher() // This causes os.Exit(1) to be called
return
}
cmd := exec.Command(os.Args[0], "-test.run=TestCrasher")
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
err := cmd.Run()
if e, ok := err.(*exec.ExitError); ok && !e.Success() {
fmt.Printf("Error is %v\n", e)
return
}
t.Fatalf("process ran with err %v, want exit status 1", err)
}
and
package foo
import (
"fmt"
"os"
)
// Coverage testing thinks (incorrectly) that the func below is
// never being called
func Crasher() {
fmt.Println("Going down in flames!")
os.Exit(1)
}
However, this method appears to suffer certain limitations:
Coverage testing with goveralls / coveralls.io does not work - see for instance the example here (the same code as above but put into github for your convenience) which produces the coverage test here, i.e. it does not record the test functions being run. NOTE that you don't need to those links to answer the question - the above example will work fine - they are just there to show what happens if you put the above into github, and take it all the way through travis to coveralls.io
Rerunning the test binary appears fragile.
Specifically, as requested, here is a screenshot (rather than a link) for the coverage failure; the red shading indicates that as far as coveralls.io is concerned, Crasher() is not being called.
Is there a way around this? Particularly the first point.
At a golang level the problem is this:
The Goveralls framework runs go test -cover ..., which invokes the test above.
The test above calls exec.Command / .Run without -cover in the OS arguments
Unconditionally putting -cover etc. in the argument list is unattractive as it would then run a coverage test (as the subprocess) within a non-coverage test, and parsing the argument list for the presence of -cover etc. seems a heavy duty solution.
Even if I put -cover etc. in the argument list, my understanding is that I'd then have two coverage outputs written to the same file, which isn't going to work - these would need merging somehow. The closest I've got to that is this golang issue.
Summary
What I am after is a simple way to run go coverage testing (preferably via travis, goveralls, and coveralls.io), where it is possible to both test cases where the tested routine exits with OS.exit(), and where the coverage of that test is noted. I'd quite like it to use the re-exec method above (if that can be made to work) if that can be made to work.
The solution should show coverage testing of Crasher(). Excluding Crasher() from coverage testing is not an option, as in the real world what I am trying to do is test a more complex function, where somewhere deep within, under certain conditions, it calls e.g. log.Fatalf(); what I am coverage testing is that the tests for those conditions works properly.
With a slight refactoring, you may easily achieve 100% coverage.
foo/bar.go:
package foo
import (
"fmt"
"os"
)
var osExit = os.Exit
func Crasher() {
fmt.Println("Going down in flames!")
osExit(1)
}
And the testing code: foo/bar_test.go:
package foo
import "testing"
func TestCrasher(t *testing.T) {
// Save current function and restore at the end:
oldOsExit := osExit
defer func() { osExit = oldOsExit }()
var got int
myExit := func(code int) {
got = code
}
osExit = myExit
Crasher()
if exp := 1; got != exp {
t.Errorf("Expected exit code: %d, got: %d", exp, got)
}
}
Running go test -cover:
Going down in flames!
PASS
coverage: 100.0% of statements
ok foo 0.002s
Yes, you might say this works if os.Exit() is called explicitly, but what if os.Exit() is called by someone else, e.g. log.Fatalf()?
The same technique works there too, you just have to switch log.Fatalf() instead of os.Exit(), e.g.:
Relevant part of foo/bar.go:
var logFatalf = log.Fatalf
func Crasher() {
fmt.Println("Going down in flames!")
logFatalf("Exiting with code: %d", 1)
}
And the testing code: TestCrasher() in foo/bar_test.go:
func TestCrasher(t *testing.T) {
// Save current function and restore at the end:
oldLogFatalf := logFatalf
defer func() { logFatalf = oldLogFatalf }()
var gotFormat string
var gotV []interface{}
myFatalf := func(format string, v ...interface{}) {
gotFormat, gotV = format, v
}
logFatalf = myFatalf
Crasher()
expFormat, expV := "Exiting with code: %d", []interface{}{1}
if gotFormat != expFormat || !reflect.DeepEqual(gotV, expV) {
t.Error("Something went wrong")
}
}
Running go test -cover:
Going down in flames!
PASS
coverage: 100.0% of statements
ok foo 0.002s
Interfaces and mocks
Using Go interfaces possible to create mock-able compositions. A type could have interfaces as bound dependencies. These dependencies could be easily substituted with mocks appropriate to the interfaces.
type Exiter interface {
Exit(int)
}
type osExit struct {}
func (o* osExit) Exit (code int) {
os.Exit(code)
}
type Crasher struct {
Exiter
}
func (c *Crasher) Crash() {
fmt.Println("Going down in flames!")
c.Exit(1)
}
Testing
type MockOsExit struct {
ExitCode int
}
func (m *MockOsExit) Exit(code int){
m.ExitCode = code
}
func TestCrasher(t *testing.T) {
crasher := &Crasher{&MockOsExit{}}
crasher.Crash() // This causes os.Exit(1) to be called
f := crasher.Exiter.(*MockOsExit)
if f.ExitCode == 1 {
fmt.Printf("Error code is %d\n", f.ExitCode)
return
}
t.Fatalf("Process ran with err code %d, want exit status 1", f.ExitCode)
}
Disadvantages
Original Exit method still won't be tested so it should be responsible only for exit, nothing more.
Functions are first class citizens
Parameter dependency
Functions are first class citizens in Go. A lot of operations are allowed with functions so we can do some tricks with functions directly.
Using 'pass as parameter' operation we can do a dependency injection:
type osExit func(code int)
func Crasher(os_exit osExit) {
fmt.Println("Going down in flames!")
os_exit(1)
}
Testing:
var exit_code int
func os_exit_mock(code int) {
exit_code = code
}
func TestCrasher(t *testing.T) {
Crasher(os_exit_mock) // This causes os.Exit(1) to be called
if exit_code == 1 {
fmt.Printf("Error code is %d\n", exit_code)
return
}
t.Fatalf("Process ran with err code %v, want exit status 1", exit_code)
}
Disadvantages
You must pass a dependency as a parameter. If you have many dependencies a length of params list could be huge.
Variable substitution
Actually it is possible to do it using "assign to variable" operation without explicit passing a function as a parameter.
var osExit = os.Exit
func Crasher() {
fmt.Println("Going down in flames!")
osExit(1)
}
Testing
var exit_code int
func osExitMock(code int) {
exit_code = code
}
func TestCrasher(t *testing.T) {
origOsExit := osExit
osExit = osExitMock
// Don't forget to switch functions back!
defer func() { osExit = origOsExit }()
Crasher()
if exit_code != 1 {
t.Fatalf("Process ran with err code %v, want exit status 1", exit_code)
}
}
disadvantages
It is implicit and easy to crash.
Design notes
If you plan to declare some logic below Exit an exit logic must be isolated with else block or extra return after exit because mock won't stop execution.
func (c *Crasher) Crash() {
if SomeCondition == true {
fmt.Println("Going down in flames!")
c.Exit(1) // Exit in real situation, invoke mock when testing
} else {
DoSomeOtherStuff()
}
}

Is there an easy way to stub out time.Now() globally during test?

Part of our code is time-sensitive, and we need to able to reserve something and then release it in 30-60 seconds, etc., which we can just do a time.Sleep(60 * time.Second).
I have just implemented the time interface, and during the test I used a stubbed implementation of the time interface, similar to this golang-nuts discussion.
However, time.Now() is called in multiple sites which means we need to pass a variable around to keep track of how much time we have actually slept.
Is there an alternative way to stub out time.Now() globally? Maybe making a system call to change the system clock?
Can we maybe write our own time package which basically wraps around the time package but allows us to change it?
Our current implementation works well. I am a Go beginner, and I am curious to see if anyone has other ideas.
With implementing a custom interface you are already on the right way. I take it you use the following advise from the golang-nuts thread you've posted:
type Clock interface {
Now() time.Time
After(d time.Duration) <-chan time.Time
}
and provide a concrete implementation
type realClock struct{}
func (realClock) Now() time.Time { return time.Now() }
func (realClock) After(d time.Duration) <-chan time.Time { return time.After(d) }
and a testing implementation.
Original
Changing the system time while making tests (or in general) is a bad idea.
You don't know what depends on the system time while executing tests and you don't want to find out the hard way by spending days of debugging into that. Just don't do it.
There is also no way to shadow the time package globally and doing that would not do
anything more you couldn't do with the interface solution. You can write your own time package
which uses the standard library and provides a function to switch to a mock time library for
testing if it is the time object you need to pass around with the interface solution that is bothering you.
The best way to design and test your code would probably be to make as much code stateless as possible.
Split your functionality in testable, stateless parts. Testing these components separately is much easier then. Also, fewer side effects means that it is much easier to make the code run concurrently.
If the methods you need to mock are few, such as Now(), you can make a package variable which can be overwritten by tests:
package foo
import "time"
var now = time.Now
// The rest of your code...which calls now() instead of time.Now()
then in your test file:
package foo
import (
"testing"
"time"
)
var now = func() time.Time { return ... }
// Your tests
I use the bouk/monkey package to replace the time.Now() calls in my code with a fake:
package main
import (
"fmt"
"time"
"github.com/bouk/monkey"
)
func main() {
wayback := time.Date(1974, time.May, 19, 1, 2, 3, 4, time.UTC)
patch := monkey.Patch(time.Now, func() time.Time { return wayback })
defer patch.Unpatch()
fmt.Printf("It is now %s\n", time.Now())
}
This works well in tests to fake out system dependencies and avoids the abused dependency injection (DI) pattern. Production code stays separate from test code and you gain useful control of system dependencies.
Also if you need to just stub time.Now you can inject the dependency as a function, e.g.,
func moonPhase(now func() time.Time) {
if now == nil {
now = time.Now
}
// Use now()...
}
// Then dependent code uses just
moonPhase(nil)
// And tests inject own version
stubNow := func() time.Time { return time.Unix(1515151515, 0) }
moonPhase(stubNow)
Granted, all that is a bit ugly if you come from a dynamic languages background (e.g., Ruby) :(
There are multiple way to mock or stub time.Now() in test code:
Passing an instance of time to the function
func CheckEndOfMonth(now time.Time) {
...
}
Passing a generator to the function
CheckEndOfMonth(now func() time.Time) {
// ...
x := now()
}
Abstract with an interface
type Clock interface {
Now() time.Time
}
type realClock struct {}
func (realClock) Now() time.Time { return time.Now() }
func main() {
CheckEndOfMonth(realClock{})
}
Package level time generator function
type nowFuncT func() time.Time
var nowFunc nowFuncT
func TestCheckEndOfMonth(t *Testing.T) {
nowFunc = func() time.Time {
return time.Now()
}
defer function() {
nowFunc = time.Now
}
// Test your code here
}
Embed time generator in struct
type TimeValidator struct {
// .. your fields
clock func() time.Time
}
func (t TimeValidator) CheckEndOfMonth() {
x := t.now()
// ...
}
func (t TimeValidator) now() time.Time {
if t.clock == nil {
return time.Now() // default implementation which fall back to standard library
}
return t.clock()
}
Each has its own pluses and minuses. The best way is to separate the function that generates the time and the processing part that uses the time.
The post Stubbing Time in golang goes into details about it and there is an example for making function with time dependency to be easily tested.
We can stub time.Now simply by using the Go package undefinedlabs/go-mpatch.
Import the go-mpatch package and put the below code snippet in the code wherever you need to stub time.Now():
mpatch.PatchMethod(time.Now, func() time.Time {
return time.Date(2020, 11, 01, 00, 00, 00, 0, time.UTC)
})
Replace the values of time.Date as per your need.
check out the sample code to check the working of go-mpatch.
go-playground sample
I found a relatively simple solution here. The basic idea is using another function called "nowFunc" to get the time.Now().
In your main, initialize this function to return time.Now(). In your test, initialize this function to return a fixed fake time.
This is the same as Jonathan Hall's answer, but I am adding a concrete example.
Concept:
You can create a global function called CurrentTime to wrap the time.now()
Reassign the CurrentTime function in tests, and make it return the desired value.
File main.go
package main
import (
"fmt"
"time"
)
func main() {
fmt.Printf("This is the current year : %d ", GetCurrentYear())
}
// 'GetCurrentYear' function uses 'CurrentTime' function internally
func GetCurrentYear() int {
return CurrentTime().Year()
}
var CurrentTime = func() time.Time {
return time.Now()
}
File main_test.go
package main
import (
"testing"
"time"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) { TestingT(t) }
type S struct{}
var _ = Suite(&S{})
func (s *S) TestCurrentYearShouldBeReturnedCorrectly(c *C) {
expectedYear := 2022
curentInstant := time.Date(expectedYear, 12, 01, 00, 00, 00, 0, time.UTC)
// Make 'CurrentTime' return hard-coded time in tests
CurrentTime = func() time.Time {
return curentInstant
}
c.Assert(GetCurrentYear(), Equals, expectedYear)
}
Here is the Go Playground link.
The simple alternative is you can use sqlmock.AnyArg() to pass time.Now() as an argument.
Example
If the query is
[sqlBuilder.Update][2](tableName).Set("last_updated", time.Now()).Where(sq.Eq{"id": id}).ToSql()
and you want to mock this, do
sqlMock.ExpectExec("UPDATE tableName SET last_updated = ? WHERE id = ?").WithArgs(sqlmock.AnyArg())
instead of
sqlMock.ExpectExec("UPDATE tableName SET last_updated = ? WHERE id = ?").WithArgs(time.Now())
You can also use the faketime method used for Go Playground.
It will keep an internal "clock" value which replaces time.Now(), and will instantly return from any call to time.Sleep(), merely increasing the internal counter.
All calls to runtime.write (for example, fmt.Println) will be prefixed with the following header:
\0 \0 P B <8-byte time> <4-byte data length> (big endian)
It was implemented here: https://github.com/golang/go/commit/5ff38e476177ce9e67375bd010bea2e030f2fe19
Using it is as simple as go run -tags=faketime test.go
Example test.go:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("Test!")
time.Sleep(time.Second * 5)
fmt.Println("Done.")
}
Output:
go run -v -tags=faketime scratch_22.go | hexdump -C
00000000 00 00 50 42 11 74 ef ed ab 18 60 00 00 00 00 06 |..PB.t....`.....|
00000010 54 65 73 74 21 0a 00 00 50 42 11 74 ef ee d5 1e |Test!...PB.t....|
00000020 52 00 00 00 00 06 44 6f 6e 65 2e 0a |R.....Done..|
0000002c
However, I wouldn't recommend using this for actual unit tests, as the change to runtime.write will probably have unintended consequences, breaking a lot of other things.
What works for me is a small struct
package clock
import "time"
type Clock struct {
MockTime time.Time
}
func (c Clock) Now() time.Time {
if c.MockTime.IsZero() {
return time.Now() // use default golang
} else {
return c.MockTime
}
}
Embed the Clock struct in your struct as a dependency, or pass it along as function parameter.