Это моя первая попытка сделать модульные тесты, поэтому, пожалуйста, будьте терпеливы со мной.
Я все еще пытаюсь написать юнит-тест библиотеки, которая преобразует списки POCO в ADO.Recordsets.
Сейчас я пытаюсь написать тест, который создает List
, преобразует его в Recordset (используя метод, который я хочу протестировать) и затем проверяет, содержат ли они одну и ту же информацию (например, если Poco.Foo == RS.Foo
, и так далее...).
Это POCO:
public class TestPoco
{
public string StringValue { get; set; }
public int Int32Value { get; set; }
public bool BoolValue { get; set; }
}
... а это тест на данный момент (я использую xUnit.net):
[Fact]
public void TheTest()
{
var input = new List();
input.Add(new TestPoco { BoolValue = true, Int32Value = 1, StringValue = "foo" });
var actual = input.ToRecordset();
Assert.Equal(actual.BoolValue, true);
Assert.Equal(actual.Int32Value, 1);
Assert.Equal(actual.StringValue, "foo");
}
Что мне не нравится, так это три утверждения в конце, по одному на каждое свойство POCO.
Я много раз читал, что несколько утверждений в одном тесте - это зло (и я понимаю причины этого, и я согласен).
Проблема в том, как от них избавиться?
У меня перед глазами отличная книга Роя Ошерова "The Art of Unit Testing" , и у него есть пример, который как раз об этом рассказывает (для тех, у кого есть книга: глава 7. 2.6, стр. 202/203):
В его примере тестируемый метод возвращает объект AnalyzedOutput
с несколькими свойствами, и он хочет утверждать все свойства, чтобы проверить, содержит ли каждое из них ожидаемое значение.
Решение в этом случае:AnalyzedOutput
, заполнить его ожидаемыми значениями и утверждать, что они равны тем, которые возвращает тестируемый метод (и переопределить Equals()
, чтобы иметь возможность сделать это).
Но я думаю, что в моем случае я не смогу этого сделать, потому что метод, который я хочу протестировать, возвращает ADODB.Recordset
.
И чтобы создать другой Recordset
с ожидаемыми значениями, мне придется сначала создать его полностью с нуля:
// this probably doesn't actually compile, the actual conversion method
// doesn't exist yet and this is just to show the idea
var expected = new ADODB.RecordsetClass();
expected.Fields.Append("BoolValue", ADODB.DataTypeEnum.adBoolean);
expected.Fields.Append("Int32Value", ADODB.DataTypeEnum.adInteger);
expected.Fields.Append("StringValue", ADODB.DataTypeEnum.adVarWChar);
expected.AddNew();
expected.BoolValue = true;
expected.Int32Value = 1;
expected.StringValue = "foo";
expected.Update();
Мне это тоже не нравится, потому что это, по сути, дублирование части кода в фактическом методе преобразования (тестируемом методе), а это еще одна вещь, которой следует избегать в тестах.
Итак... что мне теперь делать?
.
Является ли такой уровень дублирования приемлемым в этой особой ситуации, или есть лучший способ проверить это?