patterngoCritical
Is there an easy way to stub out time.Now() globally during test?
Viewed 0 times
duringtimenowstubwaygloballyouttesteasythere
Problem
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
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,
Is there an alternative way to stub out
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.
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.
Solution
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:
and provide a concrete implementation
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.
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.
Code Snippets
type Clock interface {
Now() time.Time
After(d time.Duration) <-chan time.Time
}type realClock struct{}
func (realClock) Now() time.Time { return time.Now() }
func (realClock) After(d time.Duration) <-chan time.Time { return time.After(d) }Context
Stack Overflow Q#18970265, score: 101
Revisions (0)
No revisions yet.