Introduction
The intention of NUnitEx is write short assertions where the Visual-Studio IDE intellisense is "your friend".
Assertions
The entry point of each assertion is the method Should() or its override Should(string) where the parameter is the title of the assertion (the message in NUnit terminology). After Should(). the intellisense become "your friend".
In general, each assertion allow negation (Should().Not.) and chain through .And.. Negation and .And. chain are available only where it has sense.
Where the assertion imply a cast, the additional property And.ValueOf. is available to begin a new assertion based on one of the properties of casted original actual value (examples are available below).
Boolean Assertions
bool actual;
...
actual.Should().Be.True();
actual.Should().Be.False();
Boolean assertion not allow negation nor chain.
Object instance Assertions
object actual;
...
actual.Should().Be.EqualTo(something);
actual.Should().Be.Null();
actual.Should().Be.SameInstanceAs(something);
actual.Should().Be.InstanceOf<SomeClass>();
actual.Should().Be.OfType<SomeClass>();
actual.Should().Be.AssignableFrom<SomeClass>();
actual.Should().Be.AssignableTo<SomeClass>();
actual.Should().Be.BinarySerializable();
actual.Should().Be.XmlSerializable();
Examples with negation
something.Should().Not.Be.EqualTo(new object());
something.Should().Not.Be.Null();
Examples with chain
var something = new object();
something.Should()
.Not.Be.Null()
.And
.Not.Be.EqualTo(new object()); Example ValueOf
var instanceOfClass = new InheritedClass();
instanceOfClass.Should()
.Be.AssignableTo<BaseClass>()
.And.Be.OfType<InheritedClass>()
.And.ValueOf.StringProperty
.Should().Be.Null();After the assertion Be.OfType<InheritedClass>() we know which is the concrete type of the variable instanceOfClass so we can begin a new assertion based on one of the properties of instanceOfClass (see .And.ValueOf.StringProperty.Should().Be.Null()).
Primitive struct types Assertions
var minvalue = short.MinValue;
var maxvalue = short.MaxValue;
minvalue.Should().Be.LessThan(maxvalue);
minvalue.Should().Be.LessThanOrEqualTo(minvalue + 1);
maxvalue.Should().Be.GreaterThan(minvalue);
maxvalue.Should().Be.GreaterThanOrEqualTo(maxvalue - 1);
minvalue.Should().Be.EqualTo(minvalue);
minvalue.Should().Be.IncludedIn(minvalue, maxvalue);
For Nullable<T>
int? nullable= null;
nullable.Should().Not.Have.Value();
Examples with negation and chain
5.Should().Be.GreaterThan(3).And.Not.EqualTo(4);
1.Should().Not.Be.GreaterThan(3).And.Not.EqualTo(4);
String Assertions
string actual;
...
actual.Should().Be.EqualTo("a");
actual.Should().Be.Empty();
actual.Should().Be.Null();
actual.Should().Be.NullOrEmpty();
actual.Should().Contain("some");
actual.Should().StartWith("some");
actual.Should().EndWith("ing");
actual.Should().Match("ome[tT]h");
var re = new Regex("a.b", RegexOptions.Singleline | RegexOptions.IgnoreCase);
"a\nb".Should().Match(re);
Examples with negation and chain
string something = "something";
something.Should()
.StartWith("so")
.And
.EndWith("ing")
.And
.Contain("meth");
something.Should()
.StartWith("so")
.And
.EndWith("ing")
.And
.Not.Contain("body");
something.Should()
.Not.StartWith("ing")
.And
.Not.EndWith("so")
.And
.Not.Contain("body");IEnumerable<T> Assertions
IEnumerable<int> actual;
...
actual.Should().Contain(expected);
actual.Should().Have.SameValuesAs(new[] { 3, 2, 1 });
actual.Should().Have.SameValuesAs(3, 2, 1 );
actual.Should().Have.UniqueValues();
actual.Should().Have.SameSequenceAs(new[] { 1, 2, 3 });
actual.Should().Have.SameSequenceAs(1, 2, 3 );
actual.Should().Have.Count.EqualTo(3)
actual.Should().Be.Null();
actual.Should().Be.Empty();
actual.Should().Be.SameInstanceAs(expected);
actual.Should().Be.SubsetOf(new[] { 1, 2, 3, 4 });
actual.Should().Be.SubsetOf(1, 2, 3, 4 );
actual.Should().Be.Ordered();
actual.Should().Be.OrderedAscending();
actual.Should().Be.OrderedDescending();Examples with negation and chain
var ints = new[] { 1, 2, 3 };
ints.Should()
.Have.SameSequenceAs(new[] { 1, 2, 3 })
.And
.Not.Have.SameSequenceAs(new[] { 3, 2, 1 })
.And
.Not.Be.Null()
.And
.Not.Be.Empty();
ints.Should().Contain(2).And.Not.Contain(4);
ints.Should().Contain(3).And.Not.Have.Count.LessThan(2);Action Assertions
The Action is basically to check a possible Exception executing the Action. Here the ValueOf come in play again.
(new Action(() => new AClass(null)))
.Should().Throw<ArgumentNullException>()
.And.
ValueOf.ParamName
.Should().Be.EqualTo("obj");or
(new Action(() => new object())).Should().NotThrow<ArgumentNullException>();
The same assertion, using NUnit classic Assert mixed with NUnitEx, look like:
Assert.Throws<ArgumentNullException>(() => new AClass(null))
.ParamName.Should().Be.EqualTo("obj");About Exceptions, NUnitEx offers two additional useful extensions : exception.InnerExceptions() and exception.Exceptions().
- exception.InnerExceptions() return a IEnumerable<Exception> of all Inner Exceptions.
- exception.Exceptions() return a IEnumerable<Exception> including the root Exception.
As result giving a class like this:
public class SillyClass
{
public SillyClass(object obj)
{
if (obj == null)
{
throw new ArgumentException("mess",
new ArgumentNullException("mess null",
new ArgumentOutOfRangeException("obj")));
}
}
}you can write tests like these:
(new Action(() => new SillyClass(null))
.Should().Throw<ArgumentException>()
.And.ValueOf.InnerExceptions()
.OfType<ArgumentOutOfRangeException>().First()
.ParamName.Should().Be.EqualTo("obj");
(new Action(() => new SillyClass(null))
.Should().Throw<ArgumentException>()
.And.ValueOf.InnerExceptions().Select(e => e.GetType())
.Should().Contain(typeof(ArgumentOutOfRangeException));
(new Action(() => new SillyClass(null))
.Should().Throw<ArgumentException>()
.And.ValueOf.InnerException
.Should().Be.OfType<ArgumentNullException>()
.And.ValueOf.Message.Should().Be.EqualTo("mess null");Examples with negation
(new Action(() => new object())).Should().NotThrow<ArgumentNullException>();
Note that the negation does not allow chain.
Type Assertions
private class B {}
[Serializable]
private class D1 : B { }
private class D2 : D1 { }
typeof(D1).Should().Be.EqualTo<D1>();
typeof(D1).Should().Be.SubClassOf<B>();
typeof(D1).Should().Be.AssignableFrom<D2>();
typeof(D1).Should().Have.Attribute<SerializableAttribute>();
Type t = null;
t.Should().Be.Null();
Examples with negation
typeof(D1).Should().Not.Be.EqualTo<B>();
typeof(D1).Should().Not.Be.SubClassOf<D2>();
typeof(D1).Should().Not.Be.AssignableFrom<B>();
typeof(D1).Should().Not.Be.Null();
typeof(B).Should().Not.Have.Attribute<SerializableAttribute>();
Lambda/LINQ based Assertions
For this kind of assertion there only few words to say because they are "simply" pure .NET language based assertion. Some examples may be are more clear than many words
1.Should().Satisfy(x => x == 1 || x == 2);
1.Should().Satisfy(x => x > 0);
1.Should().Satisfy(x => 2 > x);
const int y = 2;
const int z = 4;
4.Should().Satisfy(x => x == y * y);
2.Should().Satisfy(x => x == z / y);
"1".Should().Satisfy(x => x == 1.ToString());
var y = 2;
new[] { 1, 2 }.Should().Satisfy(x => x.Contains(y));
var y = new[] { 1, 2 };
var z = new[] { 2, 1 };
1.Should().Satisfy(x => x == y[0] && x == z[1]);and using LINQ extensions
new[] { 1, 2 }.Should().Satisfy(x => x.SequenceEqual(new[] { 1, 2 }));To be valid, an assertion using Should().Satisfy(expression), must include the actual parameter in one of the two sides of the expression.
Others Extensions useful for tests
System.Object Extensions
FieldValue<T>
Allow access to a private field where a public property is not available.
public class A
{
private int oneField;
public void Configure()
{
oneField = 5;
}
}
// The test based on the class
var a = new A();
a.FieldValue<int>("oneField").Should().Be.EqualTo(0);
a.Configure();
a.FieldValue<int>("oneField").Should().Be.EqualTo(5);
gRtfydtesyzzzzrizzyzzzdzzzizzzfizuzzzz