การ mock method on struct

หากใครเริ่มเขียนภาษาโก ใหม่ๆ การเขียนเทสเป็นเรื่องที่ โก สนับสนุนเครื่องมือมาให้เราพร้อม ส่วนที่เหลือก็แค่เขียนมันออกมาเท่านั้น และด่านสำคัญในการเขียนเทสของหลายๆคน หรือบางคน ที่ทำให้นั่งมองหน้าจออยู่สักพักแล้วก็นิ่งไป ก็คือการ จำลอง (mock)
ผมอยากจะยกตัวอย่างการ จำลอง แบบง่ายๆก่อน โดยวิธีง่ายสุดคือ สร้างตัวแปรเป็นฟังก์ชันแบบนี้

var Method = func() {

}

ฟังก์ชันแบบนี้เราจำลองง่ายมาก โดยสามารถเขียนซ้ำแบบเดียวกันเข้าไปในเทสได้เลย
แต่วันนี้อยากจะมาแนะนำการ จำลอง ฟังก์ชัน ที่ผูกติดอยู่กับโครงสร้าง (struct) เช่น

type presenter struct {}

func (p *presenter) method() {

}

ฟังก์ชันแบบนี้มือใหม่อาจจะไปไม่ถูก วันนี้มีตัวอย่างที่ดูไม่ยากมาฝากตามนี้เลยครับ

package main

type presenter interface {
	method() interface{}
}

type doing func() interface{}

func (d doing) method() interface{} {
	return d()
}

func mocking(d doing, p presenter) presenter {
	if d == nil {
		return p
	}
	return d
}

type actor struct {
	name string
}

func (a *actor) method() interface{} {
	println("actor method")
	return "actor"
}

var mock = func() interface{} {
	println("mock method")
	return "mock"
}

func main() {
	var p presenter
	p = new(actor)
	p.method()

	p = mocking(mock,p)
	p.method()
}

ตามตัวอย่างนี้ actor คือ โครงสร้างหลัก ที่มีฟังก์ชันชื่อ method มาผูกอยู่ กรณีนี้เราจึงใช้ presenter เข้ามาช่วย โดยทำตัวคล้าย abstract และให้ actor มาเป็น implement  ส่วน mocking จะทำการเปลี่ยน method ของ actor ไปใช้ mock แทนครับ