调用一个接口方法,该方法调用同一接口上的另一个方法。

huangapple go评论78阅读模式
英文:

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)

huangapple
  • 本文由 发表于 2021年12月22日 04:20:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/70441200.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定