Hello,

I'm new to go (and new to unit testing) and have a question about how to 
test my code. I have a package that uses a library, with a kinda big 
interface <https://godoc.org/github.com/eclipse/paho.mqtt.golang>, let's 
call it A. I don't use all the functions in A, but I want to mock the 
functionality that I do use from this interface for my unit tests. So I 
made my own interface that is a subset of the big interface, let's call it B
.

The problem is that I would also like to test the construction of the 
interface. So I made a constructor type that returns B. But I cannot pass 
the real A constructor function into my package in place of the mock B 
constructor!

Here's an example

package main


// A is an interface that does X, Y and Z
type A interface {
  X()
  Y()
  Z()
}

// B is a strict subset of A.
type B interface {
  X()
  Y()
}

// AConstructor claims to build an interface that does A
func AConstructor() A {
  return nil
}

// BConstructorType is a type of function that returns a B interface
type BConstructorType func() B


// Initialize creates a B and calls the methods in the interface. (I want 
to be able to mock A and test this function)
func Initialize(constructor BConstructorType) {
  b := constructor()
  b.X()
  b.Y()
}


func main() {
  // cannot use AConstructor (type func() A) as type BConstructorType in 
argument to Initialize Initialize(AConstructor)
  Initialize(AConstructor)
}

Why is AConstructor not of type BConstructorType? It seems like the type 
system is interpreting it's definition quite literally. Would this change 
the current compiler implementation a lot to support this kind of smart 
type checking?

I know I can use a closure to curry the constructor arguments and have an 
explicit return type as a workaround
func main() {
  Initialize(func() B { return AConstructor() })
}
but it feels clunky and unnecessary, and seems to be a bad way to have to 
call my Initialize method outside of the package

Furthermore, if I define the curried constructor as a function in my 
package to ease the pain, then it will give me a warning if B is not 
exported.
// exported func ConstructRealA returns unexported type B, which can be 
annoying to use
func ConstructRealA() B {
 return AConstructor()
}


Do y'all have any thoughts on this? Am I going about this wrong? Should I 
change the way I'm testing to avoid the whole constructor problem? I know 
generics have been considered as an addition to the language, but would 
generics solve this problem? 

Thanks,
Kevin

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/87c554bc-dbf7-4a53-9f85-18aaab06808e%40googlegroups.com.

Reply via email to