Так как каждый тест выполняется независимо с новым экземпляром объекта, нет большого количества точки к Тестовому объекту, имеющему внутреннее состояние за исключением того, что общее между setUp()
и отдельный тест и tearDown()
. Это - одна причина (в дополнение к причинам, которые другие привели), что хорошо использовать setUp()
метод.
Примечание: это - плохая идея для тестового объекта JUnit поддержать статическое состояние! При использовании статической переменной в тестах для чего-нибудь кроме отслеживания или диагностических целей Вы делаете недействительным часть цели JUnit, который является, что тесты могут (май) выполняются в любом порядке, каждый тест, работающий с новым, чистым состоянием.
преимущества для использования setUp()
состоят в том, что Вы не должны вырезать и вставлять код инициализации в каждом методе тестирования и что у Вас нет тестового кода установки в конструкторе. В Вашем случае существует мало различия. Просто создание пустого списка может быть сделано безопасно, поскольку Вы показываете его или в конструкторе, поскольку это - тривиальная инициализация. Однако как Вы и другие указали, что-либо, что может возможно бросить Exception
, должен быть сделан в setUp()
, таким образом, Вы получаете диагностический дамп стека, если он перестал работать.
В Вашем случае, где Вы просто создаете пустой список, я сделал бы тот же способ, которым Вы предлагаете: Присвойте новый список при объявлении. Особенно, потому что этот способ, которым у Вас есть опция маркировки его final
, если это имеет смысл для Вашего тестового класса.
Вы можете использовать лямбды / делегаты:
Func<string> doit = () => DoFoo();
// - or -
Func<string> doit = DoFoo;
Позже вы можете вызвать doit
точно так же, как метод:
string x = doit();
Я думаю, что ближе всего вы можете получить что-то вроде этого :
Lazy<string> x = DoFoo;
string y = x; // "use" x
С определением Lazy
, похожим на это (непроверено):
public class Lazy<T>
{
private readonly Func<T> func;
private bool hasValue;
private T value;
public Lazy(Func<T> func)
{
this.func = func;
this.hasValue = false;
}
public static implicit operator Lazy<T>(Func<T> func)
{
return new Lazy<T>(func);
}
public static implicit operator T(Lazy<T> lazy)
{
if (!lazy.hasValue)
{
lazy.value = lazy.func();
lazy.hasValue = true;
}
return lazy.value;
}
}
К сожалению, кажется, что алгоритмы определения типа компилятора не могут автоматически определить тип ] Func
и поэтому не может сопоставить его с оператором неявного преобразования. Нам нужно явно объявить тип делегата, что делает операторы присваивания более подробными:
// none of these will compile...
Lazy<string> x = DoFoo;
Lazy<string> y = () => DoFoo();
Lazy<string> z = delegate() { return DoFoo(); };
// these all work...
Lazy<string> a = (Func<string>)DoFoo;
Lazy<string> b = (Func<string>)(() => DoFoo());
Lazy<string> c = new Func<string>(DoFoo);
Lazy<string> d = new Func<string>(() => DoFoo());
Lazy<string> e = new Lazy<string>(DoFoo);
Lazy<string> f = new Lazy<string>(() => DoFoo);
Несмотря на то, что это несколько грязно, вы всегда можете использовать ключевое слово yield:
public IEnumerable<int> DoFoo() {
Console.WriteLine("doing foo");
yield return 10;
}
[Test]
public void TestMethod()
{
var x = DoFoo();
Console.WriteLine("foo aquired?");
Console.WriteLine(x.First());
}
Один из вариантов - использовать класс Lazy
, ранее из библиотеки параллельных расширений, теперь являющийся частью .Net Framework 4.0.
Он позволяет задерживать обработку данных с учетом потоков.
Вместо передачи строки x передайте делегату, который предоставляет вам string
Func<String> fooFunc=()=>DoFoo();
Почему бы просто не вызвать DoFoo (), пока вы этого не сделаете?
- Edit
Я имею в виду, что вы имеете в виду «использовать»
Например, если вы хотите, чтобы он вызывался при вызове '.ToString ()', вы всегда можете унаследовать класс и реализовать там свою функцию (но это было бы совершенно не интуитивно, IMHO).
Вы в значительной степени описываете LINQ В бою. Запрос linq описывает, как получить данные, но данные извлекаются (вызывается DoFunc) только при повторении запроса. Подумайте, можете ли вы изменить свой дизайн, чтобы он принимал IQueryable
, где вам нужна строка
.