英文:
Calling an interface method that calls another method on the same interface
问题
假设我有以下的golang接口:
type InterfaceA interface {
Method1()
Method2()
}
func (o *Obj) Method1() {
o.Method2()
}
func (o *Obj) Method2() {
}
obj1 := //实例化一个实现上述接口的类型
如果我正在为Method1
编写单元测试,我该如何创建一个用于Obj
的模拟对象,同时在一个真实的Obj
对象上执行Method1
中的代码?挑战在于Obj
调用了必须在模拟对象上的Method2
,而Method1
需要在真实对象上调用。
英文:
Say I have the following interface in golang
type InterfaceA interface {
Method1()
Method2()
}
func (o *Obj) Method1() {
o.Method2()
}
func (o *Obj) Method2() {
}
obj1 := //instantiate a type that implements the above interface
If I am writing unit tests for Method1
, how can I create a mock object for Obj
while at the same execute code in Method1
on a real Obj
object? The challenge is that Obj
calls Method2
which has to be on the mocked object while Method1
needs to be called on the real object.
答案1
得分: 2
Go语言实际上没有动态分派。Method1()
接收者o
的类型是*Obj
,因此表达式o.Method2()
将始终调用Obj.Method2()
,接口在这里根本没有参与。
所以你想要的是不可能的。但这不应该成为问题,因为我们通常在对象级别进行单元测试,而不是方法级别。
英文:
Go doesn't really have dynamic dispatch. The type of Method1()
receiver o
is *Obj
so the expression o.Method2()
will always call Obj.Method2()
, the interface is not involved here at all.
So what you want is impossible. But that shouldn't be an issue as we normally unit-test at object level, not method level.
答案2
得分: 0
我不确定我是否理解你为什么要这样做。但是你可以将“真实”对象作为模拟对象的字段,并调用其方法。
// 模拟对象有一个类型为Obj的字段
type MockObject struct {
obj Obj
}
// 然后它可以调用“真实”对象的方法
func (o *MockObject) Method1() {
o.obj.Method2()
}
func (o *MockObject) Method2() {
}
有时我会这样做来实现接口。例如,像下面这样。这样我就可以使用ListenAndServe
将服务器类型放入其中,因为它实现了ServeHTTP
。
type Server struct {
router *http.ServeMux
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.router.ServeHTTP(w, r)
}
func NewServer() *Server {
return &Server{
router: http.NewServeMux(),
}
}
s := NewServer()
http.ListenAndServe(":8080", s)
英文:
I am not sure, if I understand why you want to do this exactly. But You could add the "real" object as a field of the mock object and call its method.
// the mock object has a field of type Obj
type MockObject struct {
obj Obj
}
// then it can call the "real" objects method
func (o *MockObject) Method1() {
o.obj.Method2()
}
func (o *MockObject) Method2() {
}
I am doing something like this sometimes to implement an interface. For example, like below. This way I can use the server type and stick it into ListenAndServe
since it implements ServeHTTP
.
type Server struct {
router *http.ServeMux
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.router.ServeHTTP(w, r)
}
func NewServer() *Server {
return &Server{
router: http.NewServeMux(),
}
}
s := NewServer()
http.ListenAndServe(":8080", s)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论