2014-01-13 3 views
2

Я пишу структуру MVC, которая использует библиотеку, которая поможет управлять входными переменными (например, get, post и т. Д.).Имитация HTTP-запроса для модульного тестирования

Прямо сейчас, я тестирую переменные POST и GET, заставляя их значения в суперглобальные $ _POST и $ _GET соответственно, но я достиг контрольно-пропускного пункта при тестировании переменных PUT и DELETE.

Пример:

public function testGET() 
{ 
    $_GET['test'] = 'test value'; 

    $get_value = Input::get('test', '[default value]'); 

    assertEquals('test value', $get_value); 
} 

Есть хороший способ для имитации/моделирования эти переменные или имитировать запрос HTTP, используя различные методы, доступные (в частности, GET, POST, PUT, DELETE)?

+2

Вы бы высмеивали Input :: get(), чтобы возвращать текст, который вы ожидаете, а затем проверите свой код соответственно. Похоже, вы на правильном пути, вам просто нужно сделать Mock вместо форматирования глобальных переменных. –

ответ

3

Я иногда чувствую, что люди чрезмерно используют Design For Testability, заканчивая кодом, где 80% сложности, похоже, просто облегчает тестирование. Я чувствую, что часто лучше переключиться на функциональное тестирование на вещи, которые становятся беспорядочными для модульного теста.

Но для супер-глобалов PHP я сдаюсь. Поэтому я стараюсь избегать использования $ _POST или $ _GET в любом коде фреймворка и вместо этого использовать параметр или, если это делает код слишком уродливым, то член класса или статический член.

Таким образом, Вы получаете() функция может быть переписано следующим образом:

public static function get($name,$default,$GET=null) 
{ 
    if($GET===null)$GET=$_GET; //For non-test code 
    if(!array_key_exists($name,$GET))return $default; 
    return $GET[$name]; 
} 

Тогда ваш тест становится:

public function testGET() 
{ 
    $GET=array('test' => 'test value'); 
    $get_value = Input::get('test', '[default value]', $GET); 
    $this->assertEquals('test value', $get_value); 
} 

Это быстро становится неудобно, когда вызов на вход :: получить() глубоко погружен в иерархию вызовов; то статический член класса лучше. Чтобы использовать член класса, $ GET можно передать в функции init(). Но если иметь в init() функцию неуместно, это может быть сделано, как это:

public static $GET=null; 

public static function get($name,$default) 
{ 
    if(self::$GET===null)self::$GET=$_GET; //Init on first call 
    if(!array_key_exists($name,self::$GET))return $default; 
    return $GET[$name]; 
} 

И тогда испытание становится:

public function testGET() 
{ 
    Input::$GET=array('test' => 'test value'); 
    $get_value = Input::get('test', '[default value]'); 
    $this->assertEquals('test value', $get_value); 
} 

Помимо: другой (не тестирование) причина мне нравится этот подход что позволяет клиенту-код, чтобы выбрать использовать $_GET, $_POST, $_REQUEST и т.д. Так что я бы назвал статическую переменную self::$INPUT, и имеют init() функцию, где пользователь должен пройти в $_POST или $_GET или то, что они хотят.

Вторая половина вашего вопроса задает вопрос о тестировании данных PUT и DELETE. Однако вы не сказали, как он обрабатывается в реальном коде. Есть ли у вас какой-то код, аналогичный показанному в этом ответе: https://stackoverflow.com/a/5374881/841830

Если это так, один подход издеваться функции getContent(), как показано там, чтобы вернуть жесткий кодированный текст, вместо того, чтобы получать его от php://input. Другой подход состоит в том, чтобы иметь другую функцию (в вашем реальном классе), главным образом для тестирования, которая входит и устанавливает $this->content перед первым вызовом, который будет использовать эту переменную. ($this->content в этом ответе в основном похож на переменную self::$INPUT, о которой я упоминал ранее.)

-3

Заголовки запросов являются частью супер-глобального $ _SERVER. Вы можете установить соответствующий заголовок в $ _SERVER.Например:

<?php 
    $_SERVER['REQUEST_METHOD'] = 'PUT'; 
    // Now you should be able to pull data 
?> 

См. Руководство по PHP $ _SERVER. http://php.net/manual/en/reserved.variables.server.php

Смежные вопросы