*
wylde...@gmail.com <
wylde...@gmail.com> [190722 01:11]:
> 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!
>
A and B are different types. B is a subset of A (and they are both
interfaces), therefore a value of type A implements B, so a value of
type A can be assigned (see Assignability[1]) to a variable of type B
without any explicit conversion (see Conversions[2]) (i.e. the
conversion is performed implicitly).
However, a function returning A is not assignable to a variable of type
function returning B, even if A is assignable to B. The functions have
different types (see Function types[3]). The rules of assignability are
applied neither individually nor recursively to each argument and result
of the function; the function types as a whole must satisfy the rules of
assignability.
So, yes, the type system is intentionally very literal in its
definition. Consider a slightly different example (using types A and B
above):
var z []A = ... // an expression yielding a value of the proper type
var x []B = z
According to expectations from the design of the language, the second
assignment should not cause an allocation of a new underlying array.
But for this assignment to work, such an allocation would be necessary.
So, the language designers decided that satisfying the expectations was
more important than doing something that hides a potentially large
allocation. (Just to be explicit, the above assignment will not
compile.)
In your case, however, a simple function literal will solve your
problem:
Initialize(func() B { return B(AConstructor()) })
In fact, the explicit conversion B(...) in the return statement is
unnecessary, but I think it makes it more clear that this is an
intentional conversion. It also makes it clear why the function literal
is necessary in the first place.
...Marvin
[1]
https://golang.org/ref/spec#Assignability
[2]
https://golang.org/ref/spec#Conversions
[3]
https://golang.org/ref/spec#Function_types