与任何编程语言中的日期合作提出了一些挑战。在这篇文章中,我将展示如何在为GO应用程序编写单元测试时使用日期。
让我们去示例:
import (
"time"
"github.com/google/uuid"
)
type Food struct {
ID uuid.UUID
Name string
ExpirationDate time.Time
}
func canIEat(f Food) bool {
if time.Now().Before(f.ExpirationDate) {
return true
}
return false
}
为此代码编写单元测试的一种方法可能是:
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestCanIEat(t *testing.T) {
f1 := Food{
ExpirationDate: time.Now().AddDate(0, 0, 1),
}
assert.True(t, canIEat(f1))
f2 := Food{
ExpirationDate: time.Now().AddDate(0, 0, -1),
}
assert.False(t, canIEat(f2))
}
解决此问题的另一种方法是为time
软件包创建抽象。为此,我们将创建一个名为clock
的新软件包,其中将添加clock.go
文件:
package clock
import "time"
// Clock interface
type Clock interface {
Now() time.Time
}
// RealClock clock
type RealClock struct{}
// NewRealClock create a new real clock
func NewRealClock() *RealClock {
return &RealClock{}
}
// Now returns the current data
func (c *RealClock) Now() time.Time {
return time.Now()
}
下一步是重构将使用新软件包的功能:
import (
"time"
"github.com/eminetto/post-time/clock"
"github.com/google/uuid"
)
type Food struct {
ID uuid.UUID
Name string
ExpirationDate time.Time
}
func canIEat(c clock.Clock, f Food) bool {
if c.Now().Before(f.ExpirationDate) {
return true
}
return false
}
当canIEat
函数接收clock.Clock
接口时,我们可以在测试中使用此接口的新实现:
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
type FakeClock struct{}
func (c FakeClock) Now() time.Time {
return time.Date(2023, 6, 30, 20, 0, 0, 0, time.Local)
}
func TestCanIEat(t *testing.T) {
type test struct {
food Food
expected bool
}
fc := FakeClock{}
cases := []test{
{
food: Food{
ExpirationDate: time.Date(2020, 10, 1, 20, 0, 0, 0, time.Local),
},
expected: false,
},
{
food: Food{
ExpirationDate: time.Date(2023, 6, 30, 20, 0, 0, 0, time.Local),
},
expected: false,
},
{
food: Food{
ExpirationDate: time.Date(2023, 6, 30, 21, 0, 0, 0, time.Local),
},
expected: true,
},
}
for _, c := range cases {
assert.Equal(t, c.expected, canIEat(fc, c.food))
}
}
以这种方式,我们更好地控制了我们在测试和增益性能中使用的方法,因为不再需要像第一个示例的time.Now().AddDate(0, 0, 1)
进行日期计算。
我在这里做的是一个简单的提示,但它显示了使用interfaces in Go的概念的功能和易于使用。