Unit testing 如何在Go中为结构编写mock
我想为Unit testing 如何在Go中为结构编写mock,unit-testing,go,mocking,Unit Testing,Go,Mocking,我想为Transport函数编写一个单元测试,它需要模拟CarFactory和Car结构。请参阅以下代码: package main type Car struct { Name string } func (h Car) Run() { ... } type CarFactory struct {} func (e CarFactory) MakeCar() Car { return Car{} } func Transport(cf CarFactory) {
Transport
函数编写一个单元测试,它需要模拟CarFactory
和Car
结构。请参阅以下代码:
package main
type Car struct {
Name string
}
func (h Car) Run() { ... }
type CarFactory struct {}
func (e CarFactory) MakeCar() Car {
return Car{}
}
func Transport(cf CarFactory) {
...
car := cf.MakeCar()
car.Run()
...
}
其他的OOP语言,如java、C++或C++,我可以定义<代码> CaleMyFyCK < /C> >和<代码> CalMoC< <代码>,扩展<代码> CarFactory < /C> >和<代码> Cub/Cube >然后重写<代码> MakCARARE()/Case>方法返回<代码> CARMOK/<代码>对象< /P>
class CarMock extends Car {
public Run() {...}
}
class CarFactoryMock extends CarFactory {
public Car MakeCar() { return new CarMock(); }
}
Transport(new CarFactoryMock())
我如何在围棋中实现这一点
请注意,我可以更改运输
功能的原型和源代码,但必须保持汽车工厂
和汽车
相同,因为它们来自第三个软件包
最后一段代码是关于人和员工的,这会导致混淆。您使用的是一个界面
type Employee interface {
GetHuman() Human
}
type RealEmployee struct {
Company string
h Human
}
func (e RealEmployee) GetHuman() Human {
return e.h
}
// Call Hire with real employee
Hire(RealEmployee{h: RealHuman})
Hire
方法接受接口Employee
,然后您可以在测试中编写一个MockEmployee
结构
func Hire(e Employee) {
...
h := e.GetHuman()
fmt.Println(h.Name)
...
}
// Mock Employee instance
type MockEmployee struct {
Company string
h Human
}
func (m MockEmployee) GetHuman() Human {
return m.h
}
// Call Hire to test with mock employee
Hire(MockEmployee{h: MockHuman})
与支持完全后期绑定的其他OOP语言相比,在Go中模拟结构需要更多的代码 此代码必须保持不变,因为它是从第三方获取的:
type Car struct {
Name string
}
func (c Car) Run() {
fmt.Println("Real car " + c.Name + " is running")
}
type CarFactory struct {}
func (cf CarFactory) MakeCar(name string) Car {
return Car{name}
}
由于Go只支持接口上的后期绑定,我必须使Transport
接收接口作为参数而不是结构:
type ICar interface {
Run()
}
type ICarFactory interface {
MakeCar(name string) ICar
}
func Transport(cf ICarFactory) {
...
car := cf.MakeCar("lamborghini")
car.Run()
...
}
以下是模拟:
type CarMock struct {
Name string
}
func (cm CarMock) Run() {
fmt.Println("Mocking car " + cm.Name + " is running")
}
type CarFactoryMock struct {}
func (cf CarFactoryMock) MakeCar(name string) ICar {
return CarMock{name}
}
现在我可以轻松地使用mock传输(CarFactoryMock{})
。但是,当我尝试调用real方法Transport(CarFactory{})
时,go编译器会显示以下错误:
cannot use CarFactory literal (type CarFactory) as type ICarFactory in argument to Transport:
CarFactory does not implement ICarFactory (wrong type for MakeCar method)
have MakeCar(string) Car
want MakeCar(string) ICar
正如消息所说,MakeCar
函数从接口返回一个ICar
,但是真正的MakeCar
返回一个Car
。Go不允许这样。为了解决这个问题,我必须定义一个包装器来手动将Car
转换为ICar
type CarFactoryWrapper struct {
CarFactory
}
func (cf CarFactoryWrapper) MakeCar(name string) ICar {
return cf.CarFactory.MakeCar(name)
}
现在可以像这样调用Transport
函数:Transport(CarFactoryWrapper{CarFactory{}})
这是工作代码。@sadlil您能更新您的答案以使用
Car
、CarFactory
等吗。?很遗憾,在您发布答案后,OP已经更改了该选项。如果Run()方法返回两个或多个值,如Run()(字符串,错误)。我们可以重写Run()(string,error)方法,以便为不同的场景添加测试用例。类似于:键入CarMock struct{handleRun func()(字符串,错误)}和in-func(cm-CarMock)Run(){return cm.handleRun()}