2016-05-25 5 views
0

Я использую gorilla/context в веб-приложении. Пример в документах выглядит так:Тестирование обработчиков, которые используют Gorilla/context

func MyHandler(w http.ResponseWriter, r *http.Request) { 
    //... 

    val := context.Get(r, foo.MyKey) 

    //... 
} 

Как я могу проверить тестовый обработчик, который работает следующим образом? Единственный способ, которым я до сих пор работал, - использовать контекстный пакет внутри моих тестов. В данный момент я думаю, что я мог бы ввести параметр контекста в обработчик, но тогда я не согласуюсь с интерфейсом HandlerFunc.

ответ

1

Это классический пример cross-cutting concerns.

Вы используете третье лицо для магической обработки входных параметров для тестируемого устройства. По этому самому определению вам нужно будет сделать дополнительную настройку, чтобы подготовить context к состоянию, которое вы хотите.

Когда дело доходит до Go http handlers (что означает KISS), вам не нужно «выходить из контекста» вашей функции, чтобы получить дополнительные данные: сохраните все данные, которые вам нужны, в одном FUNC.

Лично я стараюсь избегать развращения моих обработчиков. Я думаю, что я использовал контекст горилл однажды из десятков больших сайтов, которые я построил. И это было в основном для того, чтобы обойти кешированный ответ, просто чтобы сохранить данные для конечного пользователя. Из чего я просто проигнорировал свои модульные тесты, поскольку это было вне-scrope того, что я тестировал.

Вместо этого я использую средние оболочки для настройки основ, которые я хочу в своих ручках, и соответственно изменяю подпись обработчика.

  • кэширование
  • каротажа
  • аутентификации и авторизации
  • маршалинга
  • JSON
  • контекст (например, как ожидается пользователя {} объект загружен из БД)

... и т.д.. Я бы создал промежуточное изделие, которое обертывает ваш обработчик, когда вы регистрируете его с помощью mux, который использует gorilla/context для поиска вашего cookie или userid или что-то в этом роде, скрывает этот пользовательский объект из кеша, DB, redis и т. Д., А затем вызывает ваш обработчик, который будет иметь такую ​​подпись, как:

func MyHandler(u User, p Page, w http.ResponseWriter, r *http.Request) { 
    // u is the User object loaded from middle-ware 

    // p is your global Page object... etc 
} 

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

И вы можете интегрировать тест вашего среднего уровня на сервере QA с ожидаемыми объектами пользователя и страницы в хранилище данных.

+0

Думаю, мы работаем так, как вы говорите. В этот момент мы связываем функции промежуточного программного обеспечения, которые получают требуемые данные из запроса и устанавливают его в контекст. Вместо того, чтобы обращаться к контекстному пакету непосредственно внутри обработчика, мы должны вводить значения из контекста в обработчик, правильно ли? – James

+0

Да, вот как мы это делаем. сохраняет рутки простыми и имея подпись, если метод точно отражает то, что вы используете в этом обработчике. так как MVC-фреймворки в других языках определяют маршруты MVC. – eduncan911

1

Как моя команда делает это, чтобы добавить имя к обработчику маршрута, а затем в те тесты, которые мы называем этим маршрутом по имени.

Это как добавить маршрут:

r.HandleFunc("/<route>", MyHandler).Methods("GET").Name("MyHandlerByName")

Тогда это как проверить его

r.Get("MyHandlerByName")

+0

Я использую этот метод для определения URL-адресов в коде, например перенаправления. – eduncan911

1

Один способ проверить ручки, это изменить способ, в котором они создано. например, создавая функцию, возвращающую http.HandlerFunc, эта функция может иметь параметры.Вы можете издеваться значения, отправляемые функции

Без параметров

func State() http.HandlerFunc { 
     return http.HandlerFunc(func(pResponse http.ResponseWriter, r *http.Request) { 
      // your code 
     }) 
    } 

с параметрами

func State(pParam1,pParam2,pParam3 ...) http.HandlerFunc { 
     return http.HandlerFunc(func(pResponse http.ResponseWriter, r *http.Request) { 
      // your code using pParam1,pParam2,pParam3 
     }) 
    } 

отображение будет

http.HandleFunc("/State", State()) 

или

http.HandleFunc("/State", State(value1,value2,value3 ....)) 
+0

Это средний предмет, о котором я расскажу. но у хороших у были примеры. :) – eduncan911