Fluent API jest popularne w środowisku .NET. Przez co można znaleźć frameworki wykorzystujące „płynny” interfejs, stosują go na przykład:

  • Fluent Validation MVC, służący do sprawdzania poprawności przesyłanych formularzy danych.
  • Fluent Migrator wspomagający pisanie migracji bazodanowych
  • Fluent NHibernate. Framework wspiera NHibernate ORM, służy do prostszego mapowania struktur danych na tabele w relacyjnej bazie danych. Istnieje jego odpowiednik dla Entity framework ORM.

W tematyce testów także powstał framework wykorzystujący fluent API o nazwie FluentAssertions, którego autorem jest Dennis Doomen. W tym wpisie zobaczymy przykłady jego wykorzystania. Głównym celem użycia FluentAssertions jest zwiększenie czytelności części Assert (koncepcja budowy testu Arrange-Act-Assert).
Zacznijmy od instalacji frameworka.

 

Instalacja

Do folderu FrameworksFeatures znajdującego się w solucji TestingPatterns dodałem nowy projekt o nazwie FluentAssertionsFeatures.

Rys. 1. Solucja TestingPatterns

FluentAssertions możemy dodać za pomocą opcji Manage NuGet Packagess z menu kontekstowego projektu FluentAssertionsFeatures.

Rys. 2. Opcja Manage NuGet Packagess.

W oknie NuGet wpisujemy nazwę interesującego nas frameworka. Wybieramy go z listy a następnie klikamy przycisk Install

Rys. 3. Framework FluentAssertions wyszukany w oknie NuGet.

Z opisu frameworka wynika, że wspiera praktycznie wszystkie narzędzia do testowania: MSTest, MSTest2, Gallio, NUnit, XUnit, MBUnit, MSpec, NSpec.

Alternatywną metodą instalacji FluentAssertions jest użycie Package Manager Console. Wybieramy w nim interesujący nas projekt. Następnie wpisujemy polecenie:

  • Install-Package FluentAssertions -Version 5.4.2

Rys. 4. Instalacja FluentAssertions za pomocą polecenia w Package Manager Console

Po instalacji FluentAssertions powinniśmy zobaczyć wpis w referencjach projektu FluentAssertionsFeatures.

Rys. 5. Referencje projektu FluentAssertionsFeatures po dodaniu FluentAssertions

Do przedstawienia zastosowania frameworka FluentAssertions potrzebne jest jakieś narzędzie do testów. Dlatego doinstaluję do projektu FluentAssertionsFeatures framework xUnit za pomocą poleceń użytych w Package Manager Console.

• Install-Package xunit
• Install-Package xunit.runner.visualstudio

Rys. 6. Referencje projektu FluentAssertionsFeatures po dodaniu xUnit

Teraz jesteśmy gotowi na napisanie przykładowych testów używających FluentAssertions.

 

Przykłady zastosowania

Dodajmy nowy zestaw testów o nazwie Examples do projektu FluentAssertionsFeatures. Znajdą się w nim przykładowe testy.

Rys. 7. Struktura projektu FluentAssertionsFeatures po dodaniu pliku Examples.cs

Framework umożliwia nam korzystanie z metod wywoływanych za pomocą kropki na zmiennej, która jest wynikiem testu. Przez co dokonujemy asercji sprawdzając poprawność testu. Każdy z typów ma własny zestaw metod. Najprostszym typem jest bool, zobaczmy jak użyć FluentAssertions do sprawdzenia poprawności wyniku dla tego typu danych:

[Fact]
public void Should_be_true()
{
  var result = 2 + 2 == 4;
  
  result.Should().BeTrue();
}

[Fact]
public void Should_be_false()
{
  var result = 2 - 2 == 4;

  result.Should().BeFalse();
}

Najpierw używamy metody Should(). Kolejnym krokiem jest wybór IntelliSense interesującej nas metody. Dla typu bool wybór nie jest duży:

Rys. 8. Metody dostępne dla typu bool

Dla typu numerycznego int mamy zdecydowanie więcej metod. Zobaczmy najpierw prosty test:

[Fact]
public void Should_add_two_numbers()
{
  var result = 2 + 2;

  result.Should().Be(4);
} 

Przyjrzyjmy się teraz co możemy wybrać z IntelliSense:

Rys. 9. Metody dostępne dla typu int

Dla typów referencyjnych FluentAssertions udostępnia interesującą metodę generyczną BeAssignableTo. Umożliwia ona sprawdzenie czy klasa implementuje interesujący nas interfejs lub dziedziczy po interesującej nas klasie.

[Fact]
public void Should_implement_interface()
{
  var result = new List<int> { 2, 5 };

  result.Should().BeAssignableTo<IList>();
}

[Fact]
public void Should_inherit_after()
{
  var result = new List<int> { 2, 5 };

  result.Should().BeAssignableTo<Object>();
}

Nie ma sensu abym przedstawiał wszystkie metody dostępne w FluentAssertions dla każdego typu danych lub kolekcji. Jest tego za dużo i ten wpis stał by się bardzo długi i nudny. Zachęcam samemu zapoznać się z frameworkiem. Szczególnie, że dzięki IntelliSense jest to banalnie proste. Nazwy metod są tak sugestywne, że bez problemu domyślamy się co one wykonują.

Łączenie asercji

FluentAssertions umożliwia łączenie asercji za pomocą property And, wykorzystując metodę AndConstraint. Zobaczmy przykładowy test:

[Fact]
public void Should_list_contain_two_and_not_contain_six_and_have_count_equals_two()
{
   var result = new List<int> { 2, 5 };

   result.Should().Contain(2).And
                  .NotContain(6).And
                  .HaveCount(2);
}
 

Łączenie asercji jest bardzo proste i intuicyjne, zwiększa ono o kolejny poziom czytelność testu.

Podsumowanie

Moim zdaniem FluentAssertions to bardzo przydatny framework, wykorzystuje go wręcz codziennie. Poprawia przejrzystość asercji w teście sprawiając, że są bardziej „naturalne” przez co lepiej się je czyta. Polecam zapoznanie się z tą biblioteka oraz jej stosowanie.

Adres frameworka:  https://fluentassertions.com/

One thought on “FluentAssertions”

  1. Na bieżąco czytam Twój cykl o testach i przyznaje, że sporo się dowiedziałem. Czekam na kolejne wpisy.

Comments are closed.