Maison  >  Article  >  développement back-end  >  Assertion : Mock : je ne sais pas quoi retourner car l'appel de méthode était inattendu. Erreur d'écriture du test unitaire dans Go

Assertion : Mock : je ne sais pas quoi retourner car l'appel de méthode était inattendu. Erreur d'écriture du test unitaire dans Go

王林
王林avant
2024-02-10 09:00:18494parcourir

断言:模拟:我不知道要返回什么,因为方法调用是意外的 在 Go 中编写单元测试时出错

Dans cet article, l'éditeur php Xiaoxin vous présentera une erreur courante qui se produit lors de l'écriture de tests unitaires en langage Go, à savoir les erreurs d'assertion. Lorsque nous écrivons des tests unitaires, nous rencontrons parfois des situations dans lesquelles la valeur de retour ne peut pas être déterminée, ce qui peut entraîner des erreurs d'appel de méthode inattendues. Dans cet article, nous aborderons les causes et les solutions à ce problème pour vous aider à mieux gérer les erreurs d'assertion et garantir l'exactitude et la fiabilité de vos tests unitaires.

Contenu de la question

J'écris des tests unitaires pour mes méthodes de service en utilisant testify et toutes les méthodes fonctionnent correctement sauf la méthode de mise à jour car dans la méthode de mise à jour j'appelle une autre méthode du même service dans la méthode de mise à jour (" getbyid") .

Méthode de mise à jour dans mon service :

func (ts *teamservice) update(team *team.team) apperror {
    t, err := ts.teamrepo.getbyid(team.id)
    if err != nil {
        return err
    }
    if t.teamownerid != team.teamownerid {
        return newforbiddenerror(forbiddenerr)
    }

    return ts.teamrepo.update(team)
}

Méthode de mise à jour du mockrepo :

func (t *teamrepomock) update(team *team.team) apperror {
    args := t.called(team)
    if args.error(0) != nil {
        return newnotfounderror(args.error(0))
    }

    return nil
}

Mise en place des tests :

func testupdate(t *testing.t) {
    _, teamidgen, playeridgen := setupconfig()

    t.run("update a team", func(t *testing.t) {
        teamrepo, _, ts := setupteamservice(teamidgen, playeridgen)

        teamrepo.on("update", testteam1).return(nil)
        result := ts.update(testteam1)

        assert.nil(t, result)
    })

    t.run("update a team fails", func(t *testing.t) {
        teamrepo, _, ts := setupteamservice(teamidgen, playeridgen)

        expected := oopserr
        teamrepo.on("update", testteam1).return(expected)
        result := ts.update(testteam1)

        assert.equalvalues(t, expected.error(), result.error())
    })
}

Maintenant, lorsque j'exécute le test, j'obtiens l'erreur suivante :

--- FAIL: TestUpdate (0.01s)
    --- FAIL: TestUpdate/Update_a_team (0.01s)
panic: 
assert: mock: I don't know what to return because the method call was unexpected.
    Either do Mock.On("GetByID").Return(...) first, or remove the GetByID() call.
    This method was unexpected:
        GetByID(string)
        0: ""
    at: [/home/waleem/Desktop/project/eazykhel_server/services/teamservice/team_service_init_test.go:18 /home/waleem/Desktop/project/eazykhel_server/services/teamservice/team_service.go:146 /home/waleem/Desktop/project/eazykhel_server/services/teamservice/team_service_test.go:277] [recovered]
    panic:

J'ai essayé d'appeler .on("update") avant et après avoir appelé mock.on("getbyid") dans l'implémentation de la fonction de test mais cela ne fonctionne pas et j'ai a également modifié la fonction de mise à jour du mockrepo mais cela n'a pas fonctionné. .on("update") 之前和之后调用 mock.on("getbyid") ,但它不起作用,而且我还修改了mockrepo update函数,但它没用。

解决方法

让我尝试帮助您解决问题。我通过一些简化复制了该存储库,只是为了发布相关代码。如果我在您的解决方案中没有错,有一个服务(teamservice)调用底层包(teamrepo)提供的一些方法。您想测试 teamservice 结构的 update

Solution

repo/repo.goLaissez-moi essayer de vous aider à résoudre votre problème. J'ai copié le référentiel avec quelques simplifications juste pour publier le code correspondant. Si je ne me trompe pas dans votre solution, il existe un service (teamservice) qui appelle certaines méthodes fournies par le package sous-jacent (teamrepo). Vous souhaitez tester la méthode update de la structure teamservice. Après examen, laissez-moi d'abord montrer le code, puis j'essaierai d'expliquer chaque fichier :

getbyidupdate

package repo

type team struct {
    id          int
    teamownerid int
    name        string
}

type teamrepo struct{}

func (t *teamrepo) getbyid(id int) (team, error) {
    return team{id: id, teamownerid: id, name: "myteam"}, nil
}

func (t *teamrepo) update(team team) error {
    return nil
}

Dans ce fichier, nous pouvons trouver la méthode pour simuler. La méthode est la suivante : services/service.go. Évidemment, ce n’est pas votre code réel, mais cela n’a pas d’importance pour le moment.

sut)。通过依赖注入,我们将利用通过接口 teamrepointerface 注入的 repo

package services

import (
    "errors"

    "testifymock/repo"
)

type teamservice struct {
    tr teamrepointerface
}

func newteamservice(repo teamrepointerface) *teamservice {
    return &teamservice{
        tr: repo,
    }
}

type teamrepointerface interface {
    getbyid(id int) (repo.team, error)
    update(team repo.team) error
}

func (ts *teamservice) update(team *repo.team) error {
    t, err := ts.tr.getbyid(team.id)
    if err != nil {
        return err
    }

    if t.teamownerid != team.teamownerid {
        return errors.new("forbidden")
    }

    return ts.tr.update(*team)
}

Ici, nous pouvons voir dans le code de test les services (services/service_test.go fonctions fournies par le package) qui deviendront notre système en cours de test

.

package services

import (
    "errors"
    "testing"

    "testifymock/repo"

    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/mock"
)

// 1. declare the mock struct
type teamRepoMock struct {
    mock.Mock
}

// 2. implement the interface
func (m *teamRepoMock) GetByID(id int) (repo.Team, error) {
    args := m.Called(id)

    return args.Get(0).(repo.Team), args.Error(1)
}

func (m *teamRepoMock) Update(team repo.Team) error {
    args := m.Called(team)

    return args.Error(0)
}

func TestUpdate(t *testing.T) {
    t.Run("GoodUpdate", func(t *testing.T) {
        // 3. instantiate/setup mock
        repoMock := new(teamRepoMock)
        repoMock.On("GetByID", 1).Return(repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}, nil).Times(1)
        repoMock.On("Update", repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}).Return(nil).Times(1)

        sut := NewTeamService(repoMock)
        err := sut.Update(&repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"})

        // 4. check that all expectations were met on the mock
        assert.Nil(t, err)
        assert.True(t, repoMock.AssertExpectations(t))
    })

    t.Run("BadUpdate", func(t *testing.T) {
        // 3. instantiate/setup mock
        repoMock := new(teamRepoMock)
        repoMock.On("GetByID", 1).Return(repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}, nil).Times(1)
        repoMock.On("Update", repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}).Return(errors.New("some error while updating")).Times(1)

        sut := NewTeamService(repoMock)
        err := sut.Update(&repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"})

        // 4. check that all expectations were met on the mock
        assert.Equal(t, "some error while updating", err.Error())
        assert.True(t, repoMock.AssertExpectations(t))
    })
}
repomock.on("getbyid", 1).return(repo.team{id: 1, teamownerid: 1, 姓名: "test"}, nil).times(1)Dans le code vous pouvez trouver quelques commentaires pour mieux détailler ce qui se passe. Comme vous pouvez le deviner, le problème est que cet appel manque dans le code :


🎜Si vous exécutez ma solution, cela devrait fonctionner pour vous aussi. 🎜 Si cela résout votre problème ou si vous avez d'autres questions, n'hésitez pas à me le faire savoir ! 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer