Как проверить правильность вызова зависимости

Как в Go проверить правильность вызова фиктивной зависимости.

Если у меня есть структура, которая принимает интерфейс для зависимости, после инъекции я хочу иметь возможность протестировать исходный фиктивный объект.

В моем текущем коде в этом примере я не вижу, что значение структуры изменилось. Если я изменю свой код для передачи по ссылке, это вызовет ошибку:

s.simpleInterface.Call undefined (тип * SimpleInterface - это указатель на интерфейс, а не на интерфейс)

type SimpleInterface interface {
    Call()
}

type Simple struct {
    simpleInterface SimpleInterface
}

func (s Simple) CallInterface() {
    s.simpleInterface.Call()
}

type MockSimple struct {
    hasBeenCalled bool
}

func (ms MockSimple) Call() {
    ms.hasBeenCalled = true
}

func TestMockCalled(t *testing.T) {
    ms := MockSimple{}
    s := Simple{
        simpleInterface: ms,
    }
    s.CallInterface()

    if ms.hasBeenCalled != true {
        t.Error("Interface has not been called")
    }
}

Всегда используйте приемник указателя всякий раз, когда ваш метод должен изменить состояние этого приемника. то есть func (ms *MockSimple) Call() {. Если вы этого не сделаете, то изменения в ms не будут видны за пределами тела метода, потому что ms на самом деле является копией экземпляра, для которого был вызван метод, а не самим экземпляром. Это изменение также потребует использования указателя MockSimple для установки Simple.simpleInterface. то есть Simple{simpleInterface: &ms}.

mkopriva 08.12.2018 23:27

Я попробовал это и начал получать ошибку MockSimple не реализует SimpleInterface (метод Call имеет приемник указателя)

Charles Bryant 09.12.2018 17:35

Вот почему вам нужно применить изменение, упомянутое в последнем предложении моего предыдущего комментария.

mkopriva 09.12.2018 17:37

Попробуйте переключить закомментированную строку здесь: play.golang.com/p/3FZwgT4Vhjs. Один компилирует другой - нет.

mkopriva 09.12.2018 17:39

Ах да, извинения!

Charles Bryant 09.12.2018 17:46
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
0
5
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я вижу три простых способа исправить это:

1- Измените подпись метода Call, чтобы получить указатель на MockSimple, и при создании экземпляра простой структуры укажите адрес вашего макета:

func (ms *MockSimple) Call() {
    ms.hasBeenCalled = true
}

func TestMockCalled(t *testing.T) {
    ms := MockSimple{}
    s := Simple{
        simpleInterface: &ms,
    }
    s.CallInterface()

    if ms.hasBeenCalled != true {
        t.Error("Interface has not been called")
    }
}

2- Не самое чистое решение, но все же работает. Используйте его, если вы действительно не можете использовать №1. Объявите hasBeenCalled в другом месте и измените свой MockSimple так, чтобы он содержал указатель на него:

type MockSimple struct {
    hasBeenCalled *bool
}

func (ms MockSimple) Call() {
    *ms.hasBeenCalled = true
}

func TestMockCalled(t *testing.T) {
    hasBeenCalled := false
    ms := MockSimple{&hasBeenCalled}
    s := Simple{
        simpleInterface: ms,
    }
    s.CallInterface()

    if hasBeenCalled != true {
        t.Error("Interface has not been called")
    }
}

3- Вероятно, действительно плохое решение: с использованием глобальных переменных, поэтому я бы использовал его только в крайнем случае (всегда избегайте глобального состояния). Сделайте hasBeenCalled глобальным и измените его из метода.

var hasBeenCalled bool

type MockSimple struct{}

func (ms MockSimple) Call() {
    hasBeenCalled = true
}

func TestMockCalled(t *testing.T) {
    ms := MockSimple{}
    s := Simple{
        simpleInterface: ms,
    }
    s.CallInterface()

    if hasBeenCalled != true {
        t.Error("Interface has not been called")
    }
}

Ваше здоровье!

Как и выше, первое решение начинает вызывать ошибку. MockSimple не реализует SimpleInterface (метод Call имеет приемник указателя)

Charles Bryant 09.12.2018 17:37

Ваше второе решение было лучшей реализацией

Charles Bryant 09.12.2018 17:37

@CharlesBryant, вам действительно следует использовать 1-е решение, если вы добавите & перед ms при настройке поля simpleInterface, вы не получите ошибку, которую, как вы утверждаете, получаете. Оба решения 2 и 3 нетрадиционны и не имеют преимущества перед 1.

mkopriva 09.12.2018 17:43

Другие вопросы по теме