Skip to content

Instantly share code, notes, and snippets.

@marbel82
Created April 2, 2020 07:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marbel82/628d062733b22e21398d9ada3c8e2e33 to your computer and use it in GitHub Desktop.
Save marbel82/628d062733b22e21398d9ada3c8e2e33 to your computer and use it in GitHub Desktop.

Co daje FluentAssertions?

Załóżmy, że mamy counter:

int counter = 1;

Chcemy sprawdzić, czy zmienna counter jest równa 5. Możemy to zrobić na kilka sposobów.

Assert.True(counter == 5);
Assert.IsTrue(counter == 5);
//  Message: 
//      Expected: True
//      But was:  False

Z tego asserta nie za bardzo dowiemy się, co jest nie tak, gdyż to sprawdzenie jest przeznaczone dla zmiennych boolowskich. Powinniśmy użyć odpowiedniej funkcji, w zależności od tego co chcemy sprawdzić. W tym wypadku chcemy sprawdzić equality.

Assert.AreEqual(5, counter);
//  Message: 
//      Expected: 5
//      But was:  1

Tym razem mamy już dokładniejszą informację. Oczekiwaliśmy 5, a było 1.

Bardziej czytelną wersją tych samych assertów i przez niektórych zalecaną jest wersja Assert.That().

Assert.That(counter == 5, Is.True);
Assert.That(counter, Is.EqualTo(5));

Otrzymamy takie same message ja wyżej.

A teraz popatrzcie na FluentAssertions:

counter.Should().Be(5);
//  Message: 
//    Expected counter to be 5, but found 1.

Po pierwsze łatwo się pisze sprawdzenia, bo nie musimy się zastanawiać czy powinniśmy użyć IsTrue, czy AreEqual, a dodatkowo czyta się go naturalnie "counter powinien być 5". Po drugie wiadomość zwrotna zawiera dokładniejsze informacje, "Oczekiwano, że zmienna counter będzie 5, a otrzymano 1".

Różne asercje w zależności od typu

theInt.Should().Be(1);
theInt.Should().BeInRange(1, 10);
theInt.Should().BeGreaterThan(4);,

theBoolean.Should().BeTrue();
theBoolean.Should().NotBeFalse();

theString.Should().Be("Koza");
theString.Should().BeEquivalentTo("KOZA");
theString.Should().BeEmpty();
theString.Should().Contain("za", Exactly.Once());
emailAddress.Should().Match("*@*.com");

theNullable.Should().HaveValue();

theObject.Should().NotBeNull();
theObject.Should().BeOfType<string>()
    
theDatetime.Should().BeBefore(2.March(2010));
theDatetime.Should().HaveYear(2010);

collection.Should().HaveCount(3);
collection.Should().Equal(1, 2, 5, 8);
collection.Should().Contain(8)
collection.Should().EndWith(8);

dictionary.Should().ContainKey(1);
dictionary.Should().NotContainValue("Nine");

Action act = () => subject.Foo("Hello");
act.Should().Throw<InvalidOperationException>();
await act.Should().NotThrowAfterAsync(2.Seconds(), 100.Milliseconds());

monitoredSubject
  .Should().Raise("PropertyChanged")
  .WithSender(subject)
  .WithArgs<PropertyChangedEventArgs>(args => args.PropertyName == "SomeProperty");
subject.Should().Raise().PropertyChangeFor(x => x.SomeProperty);

Action someAction = () => Thread.Sleep(100);
someAction.ExecutionTime().Should().BeLessOrEqualTo(200.Milliseconds());

Sprawdzanie wielu asercji naraz (Assertion Scopes)

Domyślne zachowanie asercji jest takie, że po pierwszym niepowodzeniu test jest przerywany. Jest jednak możliwość na obejście tego problemu za pomocą AssertionScope.

using (new AssertionScope())
{
    5.Should().Be(10);
    "Actual".Should().Be("Expected");
}
//  Message: 
//    Expected value to be 10, but found 5.
//    Expected string to be "Expected" with a length of 8, but "Actual" 
//      has a length of 6, differs near "Act" (index 0).

Dostaniemy wtedy informację o dwóch błędach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment