Как создать макет внутри тестируемой функции - PullRequest
0 голосов
/ 02 марта 2020

У меня есть набор функций, который использует пул объектов. Этот бассейн был осмеян. Работает нормально в большинстве случаев. Но в некоторых функциях я вызываю методы объектов из пула. Так что мне нужно издеваться над этими объектами тоже.

Скажем:

// ObjectGeter is a interface that is mocked
type ObjectGeter interface {
    GetObject(id int) ObjectType, error
}

// this function is under test 
func SomeFunc(og ObjectGeter,id int, otherArgument SomeType) error {
    // some actions with otherArgument  
    // and may be return an error

    obj, err := og.GetObject(id)
    if err !=nil {
        return errors.New("GetObject error")
    }

    rezult, err := obj.SomeMethod()
    if err !=nil {
        return errors.New("One of internal errors")
    }

    return rezult, nil
}

Есть ли способ проверить всю эту функцию? Я могу создать интерфейс SomeMethoder , который обернет SomeMethod () , но я не могу найти способ назначить его obj внутри SomeFun c без изменения подписи GetObject на GetObject (id int) SomeMethoder, ошибка .

В настоящее время я вижу один подход - тестирование частями .

1 Ответ

0 голосов
/ 03 марта 2020

Единственное решение, которое я нашел без изменения парадигмы - это обертка. Это довольно тривиально, но, возможно, кому-то это понадобится один раз.

Изначально у меня есть какой-то тип:

type PoolType struct {...}

func (p *PoolType)GetObject(id int) (ObjectType, error) {...}

и интерфейс, который обертывает PoolType.GetObject и что я издевался

Теперь у меня есть интерфейс:

type SomeMethoder interface {
    SomeMethod() (ResultType, error)
}

, чтобы обернуть объект, возвращаемый PoolType.GetObject () .

Для его создания у меня есть интерфейс :

type ObjectGeter interface {
    GetObject(id int) (SomeMethoder, error)
}

и введите

type MyObjectGeter struct {
    pool *PoolType
}

func New(pool *PoolType) *MyObjectGeter {
    return &MyObjectGeter{pool: pool}
}

func (p *MyObjectGeter)GetObject(id int) (SomeMethoder, error) {
    return p.pool.GetObject(id)
}

, который его реализует.

Итак:

// this function is under test 
func SomeFunc(og ObjectGeter,id int, otherArgument SomeType) error {
    // some actions with otherArgument  
    // and may be return an error

    iface, err := og.GetObject(id)
    if err !=nil {
        return errors.New("GetObject error")
    }

    rezult, err := iface.SomeMethod()
    if err !=nil {
        return errors.New("One of internal errors")
    }

    return rezult, nil
}

вызывается

og := New(pool)
SomeFunc(og,id,otherArgument)

в реальной работе.

В конце концов, чтобы проверить все SomeFun c Мне нужно:

func TestSomeFuncSuccess (t *testing.T) {
    controller := gomock.NewController(t)
    defer controller.Finish()

    objectGeter := mocks.NewMockObjectGeter(controller)
    someMethoder := mocks.NewMockSomeMethoder(controller)

    gomock.InOrder(
        args.objectGeter.EXPECT().
            GetObject(correctIdCOnst).
            Return(someMethoder, nil),
        args.someMethoder.EXPECT().
            SomeMethod().
            Return(NewResultType(...),nil).
            Times(args.test.times[1]),
    )

    result, err := SomeFunc(objectGeter,correctIdCOnst,otherArgumentConst)
    // some checks
}

Итак, единственная непроверенная часть это MyObjectGeter.GetObject этого мне достаточно.

...