web-dev-qa-db-fra.com

Est-il possible de se moquer d'une fonction importée d'un package dans golang?

J'ai la méthode suivante à tester, qui utilise une fonction importée d'un package.

import x.y.z

func abc() {
    ...
    v := z.SomeFunc()
    ... 
}

Est-il possible de se moquer de SomeFunc() dans golang?

26
Pradeep

Oui, avec un simple refactoring. Créez une variable zSomeFunc de type fonction, initialisée avec z.SomeFunc, Et faites appeler votre package à la place de z.SomeFunc():

var zSomeFunc = z.SomeFunc

func abc() {
    // ...
    v := zSomeFunc()
    // ...
}

Dans les tests, vous pouvez assigner une autre fonction à zSomeFunc, celle qui est définie dans les tests et fait tout ce que le test veut.

Par exemple:

func TestAbc(t *testing.T) {
    // Save current function and restore at the end:
    old := zSomeFunc
    defer func() { zSomeFunc = old }()

    zSomeFunc = func() int {
        // This will be called, do whatever you want to,
        // return whatever you want to
        return 1
    }

    // Call the tested function
    abc()

    // Check expected behavior
}

Voir les doublons associés/possibles: Test des scénarios os.Exit dans Go avec les informations de couverture (coveralls.io/Goveralls)

36
icza

Une chose que vous pouvez faire est la suivante:

import "x/y/z"

var someFunc = z.SomeFunc

func abc() {
    ...
    v := someFunc()
    ... 
}

Et dans votre fichier de test, vous le feriez.

func Test_abc() {
    someFunc = mockFunc
    abc()
}

Mais assurez-vous que vous effectuez cette opération de manière simultanée, si vous avez plusieurs fonctions TestXxx appelant abc ou définissant someFunc vous pouvez être mieux d'utiliser un struct avec un champ someFunc.

8
mkopriva

Avoir le pointeur de fonction et le patch de singe est celui de le faire. Mais alors, lorsque vous aurez plusieurs fonctions à simuler, vous aurez un pointeur de fonction numérique et vous devrez inutilement appeler la fonction en utilisant le pointeur de fonction uniquement.

Le mieux et l'idée recommandée d'avoir une interface et de faire de votre fonction une partie de la structure implémentant l'interface. Une fois cela fait, vous pouvez générer des simulations à l'aide de quelques bons outils disponibles.

J'utilise ceci:

mockgen -source myModule.go -package myPackage -destination myModuleMock.go

Vous pouvez l'installer en:

got get github.com/golang/mock
4