Скачать презентацию Mock и зло и другие полезные вредняшки NET meetup Скачать презентацию Mock и зло и другие полезные вредняшки NET meetup

Моки зло и другой полезный вредный инструментарий тестирования.pptx

  • Количество слайдов: 34

Mock’и зло и другие полезные вредняшки. NET meetup 2016 Павел Егоров СКБ Контур Mock’и зло и другие полезные вредняшки. NET meetup 2016 Павел Егоров СКБ Контур

? ?

Пример с Test. Case [Test. Case( Пример с Test. Case [Test. Case("it _is_ it!", Result = "it is it!")] [Test. Case("_a_", Result = "a")] [Test. Case("_a_ b", Result = "a b")] [Test. Case("b _a_", Result = "b a")] public string Convert. Underscores. To. Em. Tags(string input) { return markdown. Render(input); }

Test. Case — маркер эффективных тестов Test. Case — маркер эффективных тестов

public class Converter : IConverter { private readonly IUnits. Reference units. Reference; public Converter(IUnits. public class Converter : IConverter { private readonly IUnits. Reference units. Reference; public Converter(IUnits. Reference units. Reference) { this. units. Reference = units. Reference; } public Message. V 2 Convert(Message. V 1 message) { //. . . var unit = units. Reference. Find. Unit(unit. Id); //. . . return converted. Message; } }

Install-Package Fake. It. Easy (NSubstitute / Moq/ Rhino. Mocks) ? Install-Package Fake. It. Easy (NSubstitute / Moq/ Rhino. Mocks) ?

[Test] public void Convert() { IUnits. Reference reference = A. Fake<IUnits. Reference>(); A. Call. [Test] public void Convert() { IUnits. Reference reference = A. Fake(); A. Call. To(() => reference. Find. Unit(123)). Returns(unit 1); var v 1 = new Message. V 1(. . . 123. . . ); var converter = new Converter(reference); var v 2 = converter. Convert(v 1); Assert. That(v 2, . . . ); }

[Test. Case(. . . 123. . . )] public void Convert(int unit. Id) { [Test. Case(. . . 123. . . )] public void Convert(int unit. Id) { IUnits. Reference reference = A. Fake(); A. Call. To(() => reference. Find. Unit(unit. Id)). Returns(unit 1); var v 1 = new Message. V 1(. . . unit. Id. . . ); var converter = new Converter(reference); var v 2 = converter. Convert(v 1); Assert. That(v 2, . . . ); }

Два юзкейса моков 1. Создать зависимость-заглушку с нужным для теста поведением. Часто комбинируется с Два юзкейса моков 1. Создать зависимость-заглушку с нужным для теста поведением. Часто комбинируется с [Test. Case] 2. Проверка взаимодействия с зависимостями (В частности strict mocks) Как правило [Test. Case] не применимы

Два юзкейса моков 1. Создать зависимость-заглушку с нужным для теста поведением. Часто комбинируется с Два юзкейса моков 1. Создать зависимость-заглушку с нужным для теста поведением. Часто комбинируется с [Test. Case] 2. Проверка взаимодействия с зависимостями (В частности strict mocks) Как правило [Test. Case] не применимы

Mock’и без Test. Case’ов — маркер НЕэффективных тестов Mock’и без Test. Case’ов — маркер НЕэффективных тестов

public class Conversion. Handler : IConverter { private readonly IUnits. Reference units. Reference; public public class Conversion. Handler : IConverter { private readonly IUnits. Reference units. Reference; public Conversion. Handler( IUnits. Reference units. Reference, . . . ) { this. units. Reference = units. Reference; . . . } public void Convert(int message. Id) { Message. V 1 message. V 1 = message. Repo. Get(message. Id); //. . . var unit = units. Reference. Find. Unit(unit. Id); //. . . message. Repo. Save(message. V 2); } }

Functional Style Functional Style

public class Conversion. Handler { private readonly IMessage. Repo message. Repo; private readonly IConverter public class Conversion. Handler { private readonly IMessage. Repo message. Repo; private readonly IConverter converter; public Conversion. Handler( IMessage. Repo message. Repo, IConverter converter) {. . . } public void Convert(int message. Id) { Message. V 1 message. V 1 = message. Repo. Get(message. Id); Message. V 2 message. V 2 = converter. Convert(message. V 1); message. Repo. Save(message. V 2); } } Functional style

[Test] public void Convert. And. Save() { //Arrange var converter = A. Fake<IConverter>(options => [Test] public void Convert. And. Save() { //Arrange var converter = A. Fake(options => options. Strict()); var repo = A. Fake(options => options. Strict()); var message. V 1 = new Message. V 1(); var message. V 2 = new Message. V 2(); A. Call. To(() => repo. Get(123)). Returns(message. V 1); A. Call. To(() => converter. Convert(message. V 1)). Returns(message. V 2); var service = new Convertation. Handler(repo, converter); //Act service. Convert(123); //Assert A. Call. To(() => repo. Save(message. V 2)). Must. Have. Happened(Repeated. Exactly. Once); }

Но и с функциональным стилем есть свои сложности Но и с функциональным стилем есть свои сложности

Сравнение сложных объектов [Test] public void Test. Send. Message() { var message = Convert. Сравнение сложных объектов [Test] public void Test. Send. Message() { var message = Convert. Message(. . . ); Assert. Are. Equal(message. Text, "xyz"); Assert. Are. Equal(message. Status, Message. Status. Accepted); Assert. Are. Equal(message. Priority, 3); //. . . }

Equals [Test] public void Test. Send. Message() { var message = Convert. Message(. . Equals [Test] public void Test. Send. Message() { var message = Convert. Message(. . . ); Assert. Are. Equal( message, new Some. Message("hello", . . . )) } Da ime te. T ow. N Guid . New Guid

Install-Package Fluent. Assertions [Test] public void Test. Send. Message() { var message = Convert. Install-Package Fluent. Assertions [Test] public void Test. Send. Message() { var message = Convert. Message(. . . ); message. Should. Be. Equivalent. To( new Some. Message("hello")); }

Install-Package Fluent. Assertions [Test] public void Test. Send. Message() { var message = Convert. Install-Package Fluent. Assertions [Test] public void Test. Send. Message() { var message = Convert. Message(. . . ); message. Should. Be. Equivalent. To( new Some. Message("hello", . . . ), opt => opt. Excluding(m => m. Id). Excluding(m => m. Timestamp)); }

Сообщения об ошибках!!! Сообщения об ошибках!!!

Overspecification Overspecification

Бо-о-ольше Overspecification!!1 Бо-о-ольше Overspecification!!1

Approval. Tests ? Approval. Tests ?

Install-Package Approval. Tests [Test] [Use. Reporter(typeof(Diff. Reporter))] public void Test. Send. Message() { var Install-Package Approval. Tests [Test] [Use. Reporter(typeof(Diff. Reporter))] public void Test. Send. Message() { var message = Send. Some. Message(. . . ); Approvals. Verify(message. To. String()); }

Первый запуск теста Первый запуск теста

Второй запуск теста Time. Now Date Guid. New. Guid Второй запуск теста Time. Now Date Guid. New. Guid

Install-Package State. Printer [Test, Use. Reporter(typeof(Diff. Reporter))] public void Approvals. Test() { var message Install-Package State. Printer [Test, Use. Reporter(typeof(Diff. Reporter))] public void Approvals. Test() { var message = Convert. Message(null); var printer = new Stateprinter(); printer. Configuration. Project. Exclude(m => m. Id). Exclude(m => m. Timestamp); Approvals. Verify(printer. Print. Object(message)); }

? ?

Думай о хрупкости тестов! Думай о хрупкости тестов!

Не изобретай велосипеды — контрибьють в open source! Не изобретай велосипеды — контрибьють в open source!

TODO list: • NUnit • Fake. It. Easy • Fluent. Assertions • Approval. Tests TODO list: • NUnit • Fake. It. Easy • Fluent. Assertions • Approval. Tests • State. Printer • Deep. Equal • Auto. Fixture / NBuilder • Shouldly Павел Егоров pe@kontur. ru @xoposhiy