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".
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());
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.