Если вы занимаетесь TDD, вы должны делать небольшие шаги и сосредоточиться на том, что должны делать ваши классы. Вот пример. Вы хотите распечатать некоторые отчеты. Во-первых (я полагаю, вы выходите за пределы) вы создаете класс Report
, который должен печатать себя через Printer
(это только для примера). Итак, вы пишете тест:
[Test]
public void ShouldPrintItself()
{
Mock<IPrinter> printer = new Mock<IPrinter>();
Report report = new Report(printer.Object);
report.Text = "foo";
report.Print();
printer.Verify(p => p.Print("foo"));
}
И вы пишете некоторую реализацию для report.Print
метода. Также вы разрабатываете интерфейс IPrinter сейчас. Затем вы понимаете, что принтер иногда может показывать исключения (например, из бумаги). Это ваш случай, кстати. Таким образом, вы переименовываете report.Print
метод во что-то вроде TryPrint
, меняете первый тест и создаете новый:
[Test]
public void ShouldPrint()
{
Mock<IPrinter> printer = new Mock<IPrinter>();
Report report = new Report(printer.Object);
report.Text = "foo";
Assert.True(report.TryPrint());
printer.Verify(p => p.Print("foo"));
}
[Test]
public void ShouldNotPrint()
{
Mock<IPrinter> printer = new Mock<IPrinter>();
printer.Setup(p => p.Print(It.IsAny<string>())).Throws<Exception>();
Report report = new Report(printer.Object);
report.Text = "foo";
Assert.False(report.TryPrint());
}
И вы возвращаетесь к TryPrint
методу. Теперь вы добавляете блок try catch
вокруг вызова к принтеру и проходите тесты (то же самое, что вы должны делать в приложении):
public bool TryPrint()
{
try
{
_printer.Print(_text);
return true;
}
catch (Exception ex)
{
// of course, log exception
return false;
}
}
Когда вы закончите здесь, вы можете перейти к Printer
созданию. В вашем случае это будут тесты компонентов. Хорошие новости - у вас уже есть интерфейс IPrinter
. Итак, вы пишете тесты и проверяете, что в некоторых случаях будут выдаваться исключения:
[Test]
public void ShouldThrowExceptionWhenNoPaperLeft()
{
Printer printer = new Printer();
printer.PagesCount = 0;
Exception ex = Assert.Throws<Exception>(() => printer.Print("foo"));
Assert.That(ex.Message, Is.EqualTo("Out of paper"));
}
И, конечно, вы пишете свою компонентную реализацию, чтобы пройти этот тест. После этого ваш класс с блоком try catch
работает как положено, а ваш компонент работает как положено, вызывая исключения, когда это необходимо.