Popularity
5.4
Declining
Activity
1.8
Stable
70
82
5

Programming language: Go
License: GNU General Public License v3.0 or later
Tags: Testing     Mock    
Latest version: v1.1.0

timex alternatives and similar packages

Based on the "Mock" category.
Alternatively, view timex alternatives based on common mentions on social networks and blogs.

Do you think we are missing an alternative of timex or a related project?

Add another 'Mock' Package

README

timex

Build Status Coverage Status GoDoc

timex is a test-friendly replacement for the time package.

Usage

Just replace your time.Now() by a timex.Now() call, etc.

Mocking

Use timex.Override(...) to replace the current implementation by another one, and use the function it returns to restore the default implementation. You can't override from several tests at the same time. You can use an auto-generated by mockery mock from timexmock package, or a controlled implementation from timextest.

timexmock

There's a timexmock.Mocked(func(mocked *timexmock.Implementation) { ... }) wrapper that automatically creates a mock, sets it as the implementation to be used and defers a tear down to set the default implementation again.

Example:

func TestSleep(t *testing.T) {
    timexmock.Mocked(func(mocked *timexmock.Implementation) {
        mocked.On("Sleep", someDuration).Once()
        defer mocked.AssertExpectations(t)

        timex.Sleep(someDuration)
    })
}

timextest

Timextest provides a more complex API useful to control the behavior of concurrent programs, it is especially useful when the code interacts with timers like time.Ticker. Just like timexmock, timextest also provides a timextest.Mocked(time.Time, func(*TestImplementation)) function to make mocking easier. Few examples can be found in [timextest/example_test.go](./timextest/example_test.go), this is one of them:

func ExampleTestImplementation_NewTicker() {
    timextest.Mocked(now, func(mockedtimex *timextest.TestImplementation) {
        go func() {
            ticker := timex.NewTicker(time.Hour)
            for t := range ticker.C() {
                fmt.Printf("%s\n", t)
            }
        }()

        tickerCall := <-mockedtimex.NewTickerCalls
        tickerCall.Mock.Tick(now.Add(time.Second))
        tickerCall.Mock.Tick(now.Add(2 * time.Second))

        // Output:
        // 2009-11-10 23:00:01 +0000 UTC
        // 2009-11-10 23:00:02 +0000 UTC
    })
}

Drawbacks

Performance

There's an obvious performance impact caused by the indirection of the call, it's actually 20-30% slower, however, in absolute numbers we're talking about 30 nanoseconds per call, so you probably should not worry about that. Notice that the difference is so small that it's not easy to get a stable result.

$ go test -run=NONE -benchmem -benchtime=5s -bench=. .
goos: darwin
goarch: amd64
pkg: github.com/cabify/timex
BenchmarkTimeNow-4      49619665           112 ns/op           0 B/op          0 allocs/op
BenchmarkTimexNow-4     41256012           145 ns/op           0 B/op          0 allocs/op

If you're really worried about performance, you can disable part of the indirection by compiling with timex_disable tag, which will provide results similiar to the native implemenation calls:

$ go test -run=NONE -benchmem -benchtime=5s -bench=. -tags=timex_disable .
goos: darwin
goarch: amd64
pkg: github.com/cabify/timex
BenchmarkTimeNow-4      49866967           116 ns/op           0 B/op          0 allocs/op
BenchmarkTimexNow-4     47965780           109 ns/op           0 B/op          0 allocs/op

Dogma

Oh... yes, we're changing global variables and we'll obviously burn in hell, but if you're really into DI, you can also accept timex.Implementation interface as a dependency, and then inject either timex.Default{} or a testable implementation.