url_shortener/internal/http-server/handlers/url/save/save_test.go

103 lines
2.9 KiB
Go

package save_test
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"url-shortener/internal/http-server/handlers/url/save"
"url-shortener/internal/http-server/handlers/url/save/mocks"
"url-shortener/internal/lib/logger/handlers/slogdiscard"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
func TestSaveHandler(t *testing.T) {
cases := []struct {
name string
alias string
url string
respError string
mockError error
storageTimes int
}{
{
name: "Success",
alias: "test_alias",
url: "https://google.com",
storageTimes: 1,
},
{
name: "Empty alias",
alias: "",
url: "https://google.com",
storageTimes: 1,
},
{
name: "Empty URL",
alias: "test_alias",
url: "",
respError: "field URL is a required field",
storageTimes: 0,
},
{
name: "Invalid URL",
alias: "test_alias",
url: "invalid URL",
respError: "field URL is not a valid url",
storageTimes: 0,
},
{
name: "SaveURL Error",
alias: "test_alias",
url: "https://google.com",
respError: "failed to add url",
storageTimes: 1,
mockError: errors.New("unexpected error"),
},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
// создать мок urlSaver
urlSaverMock := mocks.NewURLSaver(t)
// описание поведения мока при вызове, если не ожидается respError или ожидается mockError (если вызовов не ноль)
// if tc.respError == "" || tc.mockError != nil {
if tc.storageTimes > 0 {
urlSaverMock.On("SaveURL", tc.url, mock.AnythingOfType("string")).Return(tc.mockError).Times(tc.storageTimes)
}
// }
// создать тестируемый handler, передаём discard logger и мок
handler := save.New(slogdiscard.NewDiscardLogger(), urlSaverMock)
// создаём json для теста
input := fmt.Sprintf(`{"url": "%s", "alias": "%s"}`, tc.url, tc.alias)
// создание http запроса к /save
req, err := http.NewRequest(http.MethodPost, "/save", bytes.NewReader([]byte(input)))
require.NoError(t, err)
// recorder для ответов
rr := httptest.NewRecorder()
// обработать http запрос
handler.ServeHTTP(rr, req)
// сравнить ожидание и реальность
require.Equal(t, rr.Code, http.StatusOK)
// получить тело запроса
body := rr.Body.String()
var resp save.Response
// Декодировать ответ в структуру
require.NoError(t, json.Unmarshal([]byte(body), &resp))
// проверить ожидание и реальность
require.Equal(t, tc.respError, resp.Error)
// TODO: add more checks
})
}
}