неверный адрес памяти или разыменование нулевого указателя при запуске тестов - PullRequest
0 голосов
/ 07 марта 2020

Я знаю, что есть похожие вопросы, но в этом случае нам не нужно иметь дело с инициализированной переменной.

В пределах pkg/cluster у меня есть 3 файла:

  • cluster.go, где находится код предприятия
  • cluster_test.go с моими тестами
  • cluster_test_mocks.go с большим количеством предварительно инициализированных значений, которые будут использоваться для насмешек.

В основном я использую насмешливые структуры, используемые в google go sdk.

У меня есть тип mock, действующий в качестве контейнера для нескольких функций, основанных на библиотеке go sdk,

type MockGcloudProvider struct{}

и нескольких инициализированных структурах (в рамках пакета), которые действуют как ложные ответы от go sdk.

import  crm "google.golang.org/api/cloudresourcemanager/v1beta1"

var mockedResourceId1 = crm.ResourceId{
    Id: "1122334455",
}

var mockedResourceId2 = crm.ResourceId{
    Id: "1122334455",
}

и вот метод, высмеивающий вышеуказанные ответы:

func (mgcloudProvider *MockGcloudProvider) GetProjectOrganization(ctx context.Context, crmProject crm.Project) (*crm.ResourceId, error) {
    var crmRsrId *crm.ResourceId
    switch crmProject.Name {
    case "project_1":
    case "project_2":
        crmRsrId = &mockedResourceId1
    case "project_3":
    case "project_4":
        crmRsrId = &mockedResourceId2
    }
    return crmRsrId, nil
    //return nil, errors.New("ERROR while mocking get project organization")
}

Когда последняя функция внедряется и вызывается из моего основного кода при выполнении тестов, она вызывает ошибку нарушения сегмента:

▶ go test -v -run TestMock
=== RUN   TestMock1
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x14afe45]

goroutine 25 [running]:
github.com/myrepo/mytool/pkg/cluster.Count.func1(0x16b3f40, 0x1a61fc0, 0x16b3d40, 0xc0000a6010, 0x15f3eba, 0x10, 0xc0001d46c0, 0xc
0000a6c10, 0xc0000a6c20, 0xc0001d4690, ...)
        /Users/panteliskaramolegkos/Workspace/mytool/pkg/cluster/cluster.go:111 +0x1d5
created by github.com/myrepo/mytool/pkg/cluster.Count
        /Users/panteliskaramolegkos/Workspace/mytool/pkg/cluster/cluster.go:105 +0x487
exit status 2
FAIL    github.com/myrepo/mytool/pkg/cluster   0.538s

Вот фактический вызов бизнес-кода:

projects, err := gcp.ListProjects(ctx)
    if err != nil {
        return nil, errors.New("ERROR: Unable to list projects")
    }
    wg.Add(len(projects))
    for _, v := range projects {
        go func(project crm.Project) {
            parentOrganization, err := gcp.GetProjectOrganization(ctx, project)
            if err != nil {
                log.Println("ERROR retrieving parent organization for: ", project, err)
            }
            if org != "all" {
                if organizatonMap[parentOrganization.Id] != org {
                    wg.Done()
                    return
                }
            }
(goroutine continues...)

Я знаю, что это сложно, просто сделать длинный снимок, который каждый делает из этого беспорядка ...

Ответы [ 2 ]

3 голосов
/ 07 марта 2020

Оператор switch в Go ведет себя иначе, чем C и связанных языках. Таким образом,

    case "project_1":
    case "project_2":
        // do something

означает, что для случая project_1 ничего не сделано, что на других языках (с которыми, я подозреваю, вы знакомы) выглядит так:

    case "project_1":
        break;
    case "project_2":
        /* do something */
        break;

Сделайте так:

    switch crmProject.Name {
    case "project_1", "project_2":
        crmRsrId = &mockedResourceId1
    case "project_3", "project_4":
        crmRsrId = &mockedResourceId2
    default:
        // maybe handle this by returning an error
    }
0 голосов
/ 07 марта 2020

Питер прав, вам нужно fallthrough заявления по делам project_1 и project_3 . Пример: https://play.golang.org/p/ts2CVoQfcc1

Вы также можете изменить функцию GetProjectOrganization для инициализации локальной переменной вместо указателя на локальную переменную для случаев по умолчанию. Пример: https://play.golang.org/p/iG3mLQA-vTG

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...