Home > Software design >  How can I test method in proper way in my case?
How can I test method in proper way in my case?

Time:09-10

I've written this code for education purposes, now I need to write some test for it. First, I need to test method Worker, but I don't understand how can I do it properly? I'm totally new to test and to Go generally.

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)
        }
    }
}

I write some lines of testing code and I suppossed to check if Worker return nil when ctx.Done() is passed to channel Now this test doesn't work, it's stuck maybe because of infinite cycle in worker method. Then I need to check if method takes messages from queue and pass it to Download method.

package worker

import (
    "context"
    "errors"
    "testing"

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

type MockQueue struct {
    mock.Mock
}

type MockDownloader struct {
    mock.Mock
}


func (m *MockQueue) TakeMessage() (<-chan string, error) {
    strCh := make(chan string)
    strCh <- "some_url/some.txt"
    return strCh, nil
}


func (d *MockDownloader) Download(url string) error {
    if url == "some_url/some.txt" {
        return nil
    } else {
        return errors.New(url)
    }
}


func TestWorkerCloseContext(t *testing.T) {
    ctx, cancel := context.WithCancel(context.Background())
    resultCh := make(chan error)
    newQueue := &MockQueue{}
    newDownload := &MockDownloader{}
    newWorker := Worker{newQueue, newDownload}
    go func() {
        resultCh <- newWorker.Worker(ctx)
    }()
    cancel()
    assert.Nil(t, <-resultCh)
}

func TestWorkerMessageReceive(t \*testing.T) {
   ctx, cancel := context.WithCancel(context.Background())
   resultCh := make(chan error)
   newQueue := &MockQueue{}
   newDownload := &MockDownloader{}
   newWorker := Worker{newQueue, newDownload}
   go func() {
       resultCh \<- newWorker.Worker(ctx)
    }()
   //some code here
}

CodePudding user response:

Go comes with a pretty extensive built-in testing library. See https://pkg.go.dev/testing

I would recommend looking at the below tutorials:

  •  Tags:  
  • go
  • Related