@Ciscoridze

Как протестировать метод с помощью testify?

Пытаюсь разобраться с тестирование в Go, но что-то никак не получается уйти дальше написания простых unit-тестов для тривиальных функций. Помогите разобраться и написать unit-тест для метода Worker, который принимает ссылку на файл из очереди и скачивает этот файл.

package worker

import (
	"context"
	"fmt"
)

type Queue interface {
	TakeMessage() (<-chan string, error)
}

type Download interface {
	Download(url string) error
}

type Worker struct {
	queue    Queue
	download Download
}

func NewWorker(queue Queue, download Download) *Worker {
	newWorker := Worker{}
	newWorker.queue = queue
	newWorker.download = download

	return &newWorker
}

func (w *Worker) Worker(ctx context.Context) error {
	msgs, err := w.queue.TakeMessage()
	if err != nil {
		return fmt.Errorf("error while consume queue: %w", err)
	}
	for {
		select {
		case <-ctx.Done():
			return nil
		case msg := <-msgs:
			fmt.Println(msg)
			w.download.Download(msg)
		}
	}
}
  • Вопрос задан
  • 164 просмотра
Пригласить эксперта
Ответы на вопрос 2
@12rbah
Помогите разобраться и написать unit-тест для метода Worker
А что именно, вы хотите протестировать, ну или какая цель у этих тестов? Писать тесты ради тестов обыно плохая идея, т.к. мало желания написать тест, нужно понимать зачем его писать. Для го есть хорошая книга тут, думаю для вашего случая достаточно.
Ответ написан
Комментировать
@khevse
Два разных способа с использование обычного табличного теста и с использованием testify.Suite. Оба варианта делаю одно и тоже.

package worker

import (
  "context"
  "errors"
  "fmt"
  "testing"
  "time"

  "github.com/stretchr/testify/require"
  "github.com/stretchr/testify/suite"
)

type TestQueue struct {
  ch     chan string
  errRes error
}

func NewTestQueueWithErr(errRes error) *TestQueue {
  return &TestQueue{
    errRes: errRes,
  }
}

func NewTestQueueWithRes(res string) *TestQueue {
  ch := make(chan string, 1)
  ch <- res

  return &TestQueue{
    ch: ch,
  }
}

func NewTestQueueWithoutRes() *TestQueue {
  return &TestQueue{
    ch: make(chan string),
  }
}

func (t *TestQueue) TakeMessage() (<-chan string, error) {
  if t.errRes != nil {
    return nil, t.errRes
  }
  return t.ch, nil
}

type TestDownload struct {
  errRes error
}

func NewTestDownload(err error) *TestDownload {
  return &TestDownload{
    errRes: err,
  }
}

func (t *TestDownload) Download(_ string) error {
  return t.errRes
}

// TABLE TEST

func TestWorker(t *testing.T) {
  testErr := errors.New("fail")

  for _, tc := range []struct {
    Name     string
    Queue    Queue
    Download Download
    WantErr  error
  }{
    {
      Name:     "success",
      Queue:    NewTestQueueWithRes("uri"),
      Download: NewTestDownload(nil),
      WantErr:  nil,
    },
    {
      Name:     "error",
      Queue:    NewTestQueueWithErr(testErr),
      Download: NewTestDownload(nil),
      WantErr:  testErr,
    },
  } {
    t.Run(tc.Name, func(t *testing.T) {
      assert := require.New(t)

      ctx, ctxCancel := context.WithTimeout(context.Background(), time.Millisecond)
      defer ctxCancel()

      worker := NewWorker(tc.Queue, tc.Download)
      err := worker.Worker(ctx)
      if tc.WantErr != nil {
        assert.ErrorIs(err, tc.WantErr)
      } else {
        assert.NoError(err)
      }
    })
  }
}

// SUITE TEST

func TestWorkerSuite(t *testing.T) {
  suite.Run(t, &WorkerSuite{})
}

type WorkerSuite struct {
  suite.Suite
}

func (s *WorkerSuite) BeforeTest(_, name string) {
  fmt.Println("todo init:", name)
}

func (s *WorkerSuite) TestSuccess() {
  ctx, ctxCancel := context.WithTimeout(context.Background(), time.Millisecond)
  defer ctxCancel()

  worker := NewWorker(NewTestQueueWithRes("data"), NewTestDownload(nil))
  s.Require().NoError(worker.Worker(ctx))
}

func (s *WorkerSuite) TestError() {
  testErr := errors.New("fail")

  ctx, ctxCancel := context.WithTimeout(context.Background(), time.Millisecond)
  defer ctxCancel()

  worker := NewWorker(NewTestQueueWithErr(testErr), NewTestDownload(nil))
  s.Require().ErrorIs(worker.Worker(ctx), testErr)
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы