package main
import "fmt"
type I1 interface {
A() string
B() string
}
type S1 struct {
name string
i I1
}
func NewS1(name string) *S1 {
s := &S1{
name: name,
}
s.i = s
return s
}
func (s *S1) A() string {
// This is the method I want to override in my tests
return "A() was called"
}
func (s *S1) B() string {
return s.i.A()
}
func main() {
s1 := NewS1("no matter")
fmt.Println(s1.B())
}
package main
import (
"log"
"testing"
)
type S1Mock struct {
*S1
}
func (*S1Mock) A() string {
return "A() from mock was called!"
}
func TestS1_B(t *testing.T) {
s1mock := S1Mock{NewS1("lol")}
s1mock.i = &s1mock
if s1mock.B() != "A() from mock was called!" {
log.Fatal("error")
}
}
I'm experimenting with Go interfaces and embedding.
The following code does exactly what I want it to do, which is to mock the B()
method during tests. But in my solution, I'm forced to keep an interface embedded in my S1
struct, which seems awkward (notice the s.i = s
in the NewS1
method).
Is there a more idiomatic way to achieve this?
Why does the following not work? The A()
method from the S1Mock
is never invoked.
package main
import "fmt"
type I1 interface {
A() string
B() string
}
type S1 struct {
name string
}
func NewS1(name string) *S1 {
s := &S1{
name: name,
}
return s
}
func (s *S1) A() string {
// Doing things this is the method I want to override
return "A() was called"
}
func (s *S1) B() string {
return s.A()
}
func main() {
s1 := NewS1("no matter")
fmt.Println(s1.B())
}
package main
import (
"log"
"testing"
)
type S1Mock struct {
*S1
}
func (*S1Mock) A() string {
return "A() from mock was called!"
}
func TestS1_B(t *testing.T) {
s1mock := S1Mock{NewS1("lol")}
if s1mock.B() != "A() from mock was called!" {
log.Fatalf("Wanted %s got %s", "A() from mock was called!", s1mock.B())
}
}