NExpect 2.0.125
Prefix Reserveddotnet add package NExpect --version 2.0.125
NuGet\Install-Package NExpect -Version 2.0.125
<PackageReference Include="NExpect" Version="2.0.125" />
<PackageVersion Include="NExpect" Version="2.0.125" />
<PackageReference Include="NExpect" />
paket add NExpect --version 2.0.125
#r "nuget: NExpect, 2.0.125"
#:package NExpect@2.0.125
#addin nuget:?package=NExpect&version=2.0.125
#tool nuget:?package=NExpect&version=2.0.125
NExpect
An assertions framework for .NET with a BDD-like feel, inspired by Chai and Jasmine, designed to be user-extensible
Goals
- Expect(NExpect).To.Be.Readable();
- Because code is for co-workers, not compilers. And your tests are part of your documentation.
- Expect(NExpect).To.Be.Expressive();
- Because the intent of a test should be easy to understand. The reader can delve into the details when she cares to.
- Expect(NExpect).To.Be.Extensible();
- Because I can't predict every use-case. I believe that your assertions framework should enable expressive, readable tests through extension.
Tutorial / blog posts:
https://fluffynuts.github.io/NExpect dev.to
Usage
- Download from nuget.org:
install-package nexpect - Import Expectations statically:
using static NExpect.Expectations;
Expectinside your tests, with fluent syntax:
// simple equality checks
Expect(1).To.Equal(1);
Expect(true).To.Not.Be.False(); // alt. grammar
Expect(null).To.Be.Null();
// - with negation, order doesn't matter
Expect("moo").Not.To.Equal("cow");
Expect("moo").To.Not.Equal("cow");
Expect(true).Not.To.Be.False();
Expect(false).To.Not.Be.True();
// exceptions
Expect(() => { }).Not.To.Throw();
Expect(() =>
{
throw new ArgumentException("moo", "moo cow");
}).To.Throw<ArgumentException>()
.With.Message.Containing("moo")
.And.("cow");
// smarter string tests, with fluency
Expect(someString).To.Contain("moo").And("cow");
Expect("moo, said the cow")
.To.Start.With("moo")
.And.Contain("said")
.Then("the")
.And.End.With("cow");
// collection tests
Expect(someCollection).To.Contain.Exactly(2)
.Matched.By(item => item.IsWhatWeWant());
Expect(someCollection).To.Contain.Only(1)
.Deep.Equal.To(new { id = 42, name = "Douglas" });
Expect(someFlags).To.Contain.At.Least(3)
.Equal.To(true);
Expect(new[] { 1, 2, 3 })
.To.Be.Ordered.Ascending();
Expect(new[] { "c", "b", "a" })
.To.Be.Ordered.Descending();
// type testing
Expect(someObject).To.Be
.An.Instance.Of<Cow>();
// deep and intersection equality testing
var person = new {
id = 1,
name = "bob"
};
Expect(person)
.To.Deep.Equal(new { id = 1, name = "bob" });
Expect(person)
.To.Intersection.Equal(new { name = "bob" });
// deep equality testing with excluded props
Expect(person)
.To.Deep.Equal(new { id = 1, name = "sarah" }, exclude: [ "name" ]);
// or
Expect(person)
.Omitting("name")
.To.Deep.Equal(new { id = 1, name = "sipho" });
Extending
Mostly, you can extend by adding extension methods for ICanAddMatcher<T> where T is the type you want. You can also extend at any point in the grammar -- some of the "better" points are ITo<T>, IBe<T>, IHave<T>, IA<T>, IAn<T>. You will need another namespace import:
using NExpect.MatcherLogic
And your extension methods can be like:
public static class MyMatchers
{
public static void Five(this IBe<int> continuation)
{
continuation.AddMatcher(actual =>
{
var passed = actual == 5;
var message = passed
? $"Expected {actual} not to be 5"
: $"Expected {actual} to be 5";
return new MatcherResult(passed, message);
});
}
}
// somewhere else...
[Test]
public void FifteenDividedByThree_ShouldEqual_Five()
{
var result = 15 / 3;
Expect(result).To.Be.Five();
}
// Yes, yes, simple example is simple.
If you've ever written a Jasmine matcher, this should feel familiar.
If you have a bunch of existing expectations that you'd like to wrap
up into a nicely-named matcher, .Compose has you covered:
// before
var cow = animalFactory.MakeCow();
var beetle = animalFactory.MakeBeetle();
// animal factory should make a Jersey cow
Expect(cow.Classification).To.Equal("Mammal");
Expect(cow.Legs).To.Equal(4);
Expect(cow.HasTail).To.Be.True();
Expect(cow.HasHorns).To.Be.True();
Expect(cow.HasSpots).To.Be.True();
// Animal factory should make a rhinoceros beetle
Expect(beetle.Classification).To.Equal("Insect");
Expect(beetle.Legs).To.Equal(6);
Expect(beetle.HasTail).To.Be.False();
Expect(beetle.HasHorns).To.Be.True();
Expect(beetle.HasSpots).To.Be.False();
// after
var cow = animalFactory.MakeJerseyCow();
var beetle = animalFactory.MakeRhinocerosBeetle();
Expect(cow).To.Be.A.JerseyCow();
Expect(beetle).To.Be.A.RhinocerosBeetle();
// elsewhere:
public static class AnimalMatchers
{
// the IMore<T> interface allows fluent chaining of expectations
// eg:
// Expect(cow).To.Be.A.JerseyCow()
// .And
// .Not.To.Be.A.FrieslandCow();
public static IMore<Animal> JerseyCow(this IA<Animal> a)
{
return a.Compose(actual =>
{
Expect(cow.Classification).To.Equal("Mammal");
Expect(cow.Legs).To.Equal(4);
Expect(cow.HasTail).To.Be.True();
Expect(cow.HasHorns).To.Be.True();
Expect(cow.HasSpots).To.Be.True();
});
}
public static IMore<Animal> RhinocerosBeetle(this IA<Animal> a)
{
return a.Compose(actual =>
{
Expect(beetle.Classification).To.Equal("Insect");
Expect(beetle.Legs).To.Equal(6);
Expect(beetle.HasTail).To.Be.False();
Expect(beetle.HasHorns).To.Be.True();
Expect(beetle.HasSpots).To.Be.False();
});
}
}
When one of the inner expectations fails, NExpect attempts to construct a nice failure message. As with all expectations, you can always make failures easier to understand with a custom message string or generator:
using NExpect.Implementations;
using NExpect.MatcherLogic;
using NExpect;
using static NExpect.Expectations;
public static class AnimalMatchers
{
public static IMore<Animal> JerseyCow(this IA<Animal> a)
{
return a.Compose(actual =>
{
// the Stringify extension method, available on all types,
// comes from NExpect.Implementation.MessageHelpers and
// produces a string representation of the object it's
// operating on which is similar to JSON, so it's easier
// to read what the object was
var customMessage = $"Expected {actual.Stringify()} to be a cow";
Expect(cow.Classification).To.Equal("Mammal", customMessage);
Expect(cow.Legs).To.Equal(4, customMessage);
Expect(cow.HasTail).To.Be.True(customMessage);
Expect(cow.HasHorns).To.Be.True(customMessage);
Expect(cow.HasSpots).To.Be.True(customMessage);
});
}
public static IMore<Animal> RhinocerosBeetle(this IA<Animal> a)
{
return a.Compose(actual =>
{
// we can use a generator func to delay generation of the message
// which is especially helpful if message generation is expensive
// and we'd only like to spend that cpu time on a failure
Func<string> customMessageGenerator = () => $"Expected {actual.Stringify()} to be a cow";
Expect(beetle.Classification).To.Equal("Insect", customMessageGenerator);
Expect(beetle.Legs).To.Equal(6, customMessageGenerator);
Expect(beetle.HasTail).To.Be.False(customMessageGenerator);
Expect(beetle.HasHorns).To.Be.True(customMessageGenerator);
Expect(beetle.HasSpots).To.Be.False(customMessageGenerator);
});
}
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.6.2
-
.NETStandard 2.0
- No dependencies.
NuGet packages (6)
Showing the top 5 NuGet packages that depend on NExpect:
| Package | Downloads |
|---|---|
|
NExpect.Matchers.NSubstitute
This library offers NSubistitute-specific extensions so you can have Expect-style syntax for your NSubstitute assertions. For example, one may previously have done: ``` Expect(result).To.Equal(expected); someService.Received(1).SomeMethodCall(); ``` and now you can keep it consistent: ``` Expect(result).To.Equal(expected); Expect(someService).To.Have.Received(1).SomeMethodCall(); ``` |
|
|
NExpect.Matchers.AspNetCore
This library adds ASP.Net core extensions for NExpect so you can test your [Route] and [Http*] annotations like so: ``` Expect(typeof(SomeController) .To.Have.Method(nameof(SomeController.MethodName)) .Supporting(HttpMethod.Delete) .And(HttpMethod.Post) .With.Route("first-route") .And.Route("second-route"); ``` |
|
|
NExpect.Matchers.Xml
This library offers XML-specific assertions so you can, for instance: ``` var doc = XDocument.Parse(someXml); Expect(doc) .To.Have.Element("//path/to/element") .With.Attribute("some-attribute") .Having.Value("expected-attribute-value"); ``` |
|
|
NExpect.Matchers.AspNetMvc
This library adds ASP.Net core extensions for NExpect so you can test your [Route] and [Http*] annotations like so: ``` Expect(typeof(SomeController) .To.Have.Method(nameof(SomeController.MethodName)) .Supporting(HttpMethod.Delete) .And(HttpMethod.Post) .With.Route("first-route") .And.Route("second-route"); ``` |
|
|
NExpect.NSubstitute
NSubstitute extensions for NExpect so you can: ``` Expect(foo).(Not).To.Have.Received().Method(..); ``` |
GitHub repositories (3)
Showing the top 3 popular GitHub repositories that depend on NExpect:
| Repository | Stars |
|---|---|
|
clojure/clojure-clr
A port of Clojure to the CLR, part of the Clojure project
|
|
|
Rohland/htmldiff.net
Html Diff algorithm for .NET
|
|
|
fluffynuts/PeanutButter
Tasty, versatile, nutritious; goes with many things in .net.
|
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.125 | 1,012 | 12/4/2025 |
| 2.0.124 | 2,016 | 10/28/2025 |
| 2.0.123 | 1,602 | 9/17/2025 |
| 2.0.122 | 458 | 9/16/2025 |
| 2.0.121 | 844 | 9/11/2025 |
| 2.0.120 | 439 | 9/9/2025 |
| 2.0.119 | 420 | 8/12/2025 |
| 2.0.118 | 427 | 8/6/2025 |
| 2.0.117 | 622 | 7/15/2025 |
| 2.0.116 | 7,248 | 3/24/2025 |
| 2.0.115 | 1,012 | 2/25/2025 |
| 2.0.114 | 408 | 2/13/2025 |
| 2.0.113 | 287 | 2/12/2025 |
| 2.0.112 | 264 | 2/12/2025 |
| 2.0.111 | 4,083 | 12/17/2024 |
| 2.0.110 | 2,864 | 11/13/2024 |
| 2.0.109 | 336 | 11/1/2024 |
| 2.0.108 | 467 | 10/23/2024 |
| 2.0.107 | 300 | 10/23/2024 |
| 2.0.106 | 333 | 10/22/2024 |