2013-07-01 4 views
3

Допустим, у меня есть следующие структуры класса:методы тестирования блока, которые используют глобальные переменные

private string GlobalVariable = "foo"; 

public void MainMethod() 
{ 
    string bar = Baz(); 
} 

public string Baz() 
{ 
    return GlobalVariable + "qux"; 
} 

Я желаю, чтобы провести тест на единичную Baz(), используя различные значения для GlobalVariable. Однако, поскольку GlobalVariable просто вызывается внутри метода и не передается ему в качестве параметра, я не могу установить это в своем модульном методе тестирования.

Поэтому я рассмотрел изменения моей структуры:

private string GlobalVariable = "foo"; 

public void MainMethod() 
{ 
    string bar = Baz(GlobalVariable); 
} 

public string Baz(string globalVar) 
{ 
    return globalVar + "qux"; 
} 

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

Однако моя первая структура более чистая, так как я не излишне передаю значения переменных методам в качестве параметров.

Есть ли способ получить лучшее из обоих миров, не препятствуя моей структуре для проведения модульных тестов?

+2

Нет ... поэтому статические классы трудно проверить. Как вы уже выяснили, глобальное состояние плохо тестируется. –

+1

Подождите .. это статическое? Что определяет «глобальный» в вашем примере? –

+0

Я думаю, вопрос в том, как/почему изменился бы ваш «GlobalVariable» при использовании в реальном мире? Если это не так, вам действительно нужно проверить его? Если он изменит, то каким механизмом и проверит этот механизм. – Belogix

ответ

5

Я был бы соблазн иметь отдельный перегруженный метод, то я мог бы иметь один с параметром и один без ...

public string Baz() 
{ 
    return Baz(GlobalVariable); 
} 

public string Baz(string globalVar) 
{ 
    return globalVar + "qux"; 
} 

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

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


Или, если вы используете C# 4.0 можно использовать вместо optional parameters:

public string Baz(string globalVar = null) 
{ 
    if(string.IsNullOrEmpty(globalVar)) 
     globalVar = GlobalVariable; 
    return globalVar + "qux"; 
} 
+2

Перегрузка звучит как хорошая идея здесь, это даст мне преимущества обоих. Однако я должен убедиться, что это хорошо документировано, или же просмотр перегруженных методов без видимого использования в классе может смутить других разработчиков! Является ли эта стандартная практика для этого сценария? Похоже, что это будет распространенная проблема с модульным тестированием, но я не могу найти ссылок на предыдущие решения. – Curt

+0

Ну, «стандартная практика» для меня часто «что бы я ни делала». Если это то, что мне никогда не нужно было преодолевать, прежде чем я просто пойду за тем, что, похоже, будет хорошо работать. Если я получу 6 месяцев на линии и найду какие-либо проблемы с ней, то это будет уроком, который я узнал в следующий раз, когда мне нужно решить ту же проблему, где я могу попробовать другой подход. Я, конечно, использовал этот метод раньше, когда мне нужны параметры по умолчанию, но также допускаю случайное переопределение, и я не испытывал ничего, что могло бы дать мне основания не использовать его снова в будущем. – musefan

+0

Я реализовал это решение. Я изменил свое мнение об этом, вызвав путаницу, я думаю, что передача значения в качестве параметра делает метод более «единицей/компонентом», который не полагается на внешние переменные. – Curt

2

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

public string Baz() 
{ 
    return ApplicationSetting.GlobalVariable + "qux"; 
} 

затем в тесте я хотел бы сделать что-то вроде этого:

[Test] 
public void Test() 
{ 
    string expected = ApplicationSetting.GlobalVariable + "qux"; 
    Assert.AreEqual(expected, Baz()); 
} 

Тогда как код тестируемой и тест сам по себе используют те же настройки приложения источник. Это означает, что источник может измениться, но тест не сломается. Надеюсь это поможет.

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