วิธีเทสโค้ดที่ใช้ Time.Now
โค้ดที่เราใช้ time.Now()
ใน package ทำให้โค้ดเราไม่สามารถเขียนเทสแล้วเช็คได้ว่า ค่าที่ได้ตอนเทสคือะไร ทางเลือกนึงง่ายๆที่ใช้อยู่ตอนนี้เพื่อให้ทดสอบโค้ดที่ใช้ time.Now()
ได้คือใช้ตัวแปรเก็บฟังก์ชัน time.Now เอาไว้ซะ เราจะได้เปลี่ยนได้ตอนเขียนเทส
วิธีก็ง่ายๆถ้าเรามีโค้ดที่ใช้ time.Now()
ใน package เช่น
package customer
type Customer struct {
UpdatedAt time.Time
}
func (c *Customer) Save() {
c.UpdatedAt = time.Now()
}
เวลาเขียนเทสเราจะเช็คไม่ได้ว่า c.UpdatedAt
มีค่าเป็นอะไร
package customer
func TestSaveCustomer(t *testing.T) {
var c Customer
c.Save()
if c.UpdatedAt.Equal(__??__) {
t.Error("UpdatedAt is not correct")
}
}
ทางแก้ก็อย่างที่บอก ใช้ตัวแปรใน scope ของ pacakge เก็บฟังก์ชันเอาไว้
package customer
var timeNow = time.Now // ไม่ใส่ () นะเพราะเราจะเก็บตัวฟังก์ชัน ไม่ได้เรียกฟังก์ชันตรงนี้
type Customer struct {
UpdatedAt time.Time
}
func (c *Customer) Save() {
c.UpdatedAt = timeNow() // เรียกฟังก์ชันผ่านตัวแปรที่เราเก็บฟังก์ชันเอาไว้แทน
}
ทีนี้ในเทสเราก็เปลี่ยน timeNow
เป็นฟังก์ชันที่ตอบกลับ time.Time ที่เราต้องการแทนเช่น
package customer
func TestSaveCustomer(t *testing.T) {
now := time.Now() // เก็บค่า time.Now() ตอนเทสเอาไว้ไปเช็คได้อีกที
timeNow = func() time.Time { // เปลี่ยน timeNow เป็นฟังก์ชันใหม่ที่ตอบกลับเป็นค่า now ที่เราเก็บเอาไว้ก่อน
return now
}
defer func() { timeNow = time.Now } // เปลี่ยนกลับเมื่อเทสฟังก์ชันทำงานจบ
var c Customer
c.Save()
if !c.UpdatedAt.Equal(now) { // เอามาไว้เช็คตรงนี้ได้แล้ว
t.Error("UpdatedAt is not correct")
}
}
เท่านี้เราก็กำหนด time.Now() ตอนเขียนเทสได้แล้ว