GithubHelp home page GithubHelp logo

fluentassertions / fluentassertions Goto Github PK

View Code? Open in Web Editor NEW
3.6K 70.0 535.0 34.61 MB

A very extensive set of extension methods that allow you to more naturally specify the expected outcome of a TDD or BDD-style unit tests. Targets .NET Framework 4.7, as well as .NET Core 2.1, .NET Core 3.0, .NET 6, .NET Standard 2.0 and 2.1. Supports the unit test frameworks MSTest2, NUnit3, XUnit2, MSpec, and NSpec3.

Home Page: https://www.fluentassertions.com

License: Apache License 2.0

C# 99.81% PowerShell 0.09% Batchfile 0.01% Shell 0.07% F# 0.01% Visual Basic .NET 0.02%
fluent-assertions c-sharp assertions tdd bdd-style unit-testing xunit mstest hacktoberfest

fluentassertions's Introduction

Extension methods to fluently assert the outcome of .NET tests

Coveralls branch qodana GitHub Repo stars GitHub contributors GitHub last commit GitHub commit activity open issues

A very extensive set of extension methods that allow you to more naturally specify the expected outcome of a TDD or BDD-style unit tests. Works with .NET Standard 2.0 and higher, .NET Framework 4.7 and higher and .NET 6 and higher.

See https://www.fluentassertions.com for background information, usage documentation, an extensibility guide, support information and more tips & tricks.

Who created this?

Originally authored by Dennis Doomen with Jonas Nyrup as the productive side-kick. Notable contributions were provided by Artur Krajewski, Lukas Grützmacher and David Omid.

How do I build this?

Install Visual Studio 2022 17.8+ or JetBrains Rider 2021.3 as well as the Build Tools 2022 (including the Universal Windows Platform build tools). You will also need to have .NET Framework 4.7 SDK and .NET 8.0 SDK installed. Check global.json for the current minimum required version.

What are these Approval.Tests?

This is a special set of tests that use the Verify project to verify whether you've introduced any breaking changes in the public API of the library.

If you've verified the changes and decided they are valid, you can accept them using AcceptApiChanges.ps1 or AcceptApiChanges.sh. Alternatively, you can use the Verify Support plug-in to compare the changes and accept them right from inside Rider. See also the Contribution Guidelines.

Sponsors

     

With support from the following public sponsors

fluentassertions's People

Contributors

0xced avatar 94sedighi avatar adamvoss avatar alexangas avatar chvollm avatar danielmpetrov avatar davidomid avatar dennisdoomen avatar dependabot[bot] avatar energy164 avatar evangelink avatar fabiannitsche avatar fredatgithub avatar gliljas avatar iliashkolyar avatar it-vbfk avatar italuone avatar jnyrup avatar konstmsu avatar krajek avatar lg2de avatar logiclrd avatar melchiork avatar mpopdam avatar serbrech avatar serg046 avatar ulrichb avatar vbreuss avatar whymatter avatar yazgoo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fluentassertions's Issues

Hang on ShouldBeEquivalent

I'm not sure what happened, but in FluentAssertions 2.0.1, this code sample worked fine and it stopped working in 2.1.0. I simplified as much as I could to reproduce the issue and it seems confined to use NodaTime's (version 1.1) LocalTime objects.

I have a ZIP file with the solution but GitHub won't let me attach it, so I'll just paste in the code here:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using FluentAssertions;
using NodaTime;
using NUnit.Framework;

namespace HangProblem
{
public class NestedClass
{
public LocalTime Start { get; private set; }
public LocalTime End { get; private set; }
public IsoDayOfWeek DayOfWeek { get; private set; }

    public NestedClass(IsoDayOfWeek dayOfWeek,
                       LocalTime start,
                       LocalTime end)
    {
        Start = start;
        End = end;
        DayOfWeek = dayOfWeek;
    }
}

public class Class1
{
    public string Name { get; set; }
    public IEnumerable<NestedClass> Nested { get; set; }

    public Class1(string name,
                  IEnumerable<NestedClass> nested)
    {
        Name = name;
        Nested = nested;
    }
}

[TestFixture]
public class SomeTest1
{
    private static readonly LocalTime Midnight = new LocalTime(hour: 0,
                                                               minute: 0);

    private static readonly LocalTime JustBeforeMidnight = new LocalTime(hour: 23,
                                                                         minute: 59,
                                                                         second: 59);

    #region Utility Methods

    private static IEnumerable<NestedClass> GetNestedObjects()
    {
        for (var index = 0; index <= 7; index++)
        {
            var day = (IsoDayOfWeek) index;
            // skip monday or none
            if (day == IsoDayOfWeek.Monday || day == IsoDayOfWeek.None)
            {
                continue;
            }
            var obj = new NestedClass(day,
                                      new LocalTime(hour: 0,
                                                    minute: 0),
                                      new LocalTime(hour: 23,
                                                    minute: 59,
                                                    second: 59));
            yield return obj;
        }
    }

    #endregion

    #region Tests

    [Test]
    public void Fails_properly()
    {
        var actual = new NestedClass(IsoDayOfWeek.Thursday,
                                    new LocalTime(hour: 0,
                                                    minute: 0),
                                      new LocalTime(hour: 23,
                                                    minute: 59,
                                                    second: 59));
        var expected = new NestedClass(IsoDayOfWeek.Thursday,
                                     Midnight,
                                     new LocalTime(20,
                                                   59,
                                                   59));
        actual
            .Should()
            .Be(expected);
    }

    [Test]
    public void Replicate_problem_without_collection_hangs()
    {
        // arrange
        var actual = new NestedClass(IsoDayOfWeek.Thursday,
                                    new LocalTime(hour: 0,
                                                    minute: 0),
                                      new LocalTime(hour: 23,
                                                    minute: 59,
                                                    second: 59));
        var expected = new NestedClass(IsoDayOfWeek.Thursday,
                                     Midnight,
                                     new LocalTime(20,
                                                   59,
                                                   59));

        // this should fail but instead it hangs
        actual.ShouldBeEquivalentTo(expected);
    }

    [Test]
    public void ReplicateProblem_WithoutCollection_Passes()
    {
        // arrange
        var actual = new NestedClass(IsoDayOfWeek.Thursday,
                                    new LocalTime(hour: 0,
                                                    minute: 0),
                                      new LocalTime(hour: 23,
                                                    minute: 59,
                                                    second: 59));
        var expected = new NestedClass(IsoDayOfWeek.Thursday,
                                     Midnight,
                                     JustBeforeMidnight);

        actual.ShouldBeEquivalentTo(expected);
    }

    [Test]
    public void Replicate_problem_with_collection_hangs()
    {
        // arrange
        var nested = GetNestedObjects();
        var obj = new Class1("the class",
                             nested);

        // act
        var result = obj.Nested;

        // assert
        var expectedResult = new[]
                             {
                                 new NestedClass(IsoDayOfWeek.Sunday,
                                                 Midnight,
                                                 JustBeforeMidnight),
                                                 new NestedClass(IsoDayOfWeek.Tuesday,
                                                 Midnight,
                                                 JustBeforeMidnight),
                                                 new NestedClass(IsoDayOfWeek.Wednesday,
                                                 Midnight,
                                                 JustBeforeMidnight),
                                                 new NestedClass(IsoDayOfWeek.Thursday,
                                                 Midnight,
                                                 new LocalTime(20,59,59)),
                                                 new NestedClass(IsoDayOfWeek.Friday,
                                                 Midnight,
                                                 JustBeforeMidnight),
                                                 new NestedClass(IsoDayOfWeek.Saturday,
                                                 Midnight,
                                                 JustBeforeMidnight),
                             };

        // hangs
        result
            .ShouldBeEquivalentTo(expectedResult);
    }

    #endregion
}

}

Exception, when parsing property expression in EquivalencyAssertionOptions for ShouldBeEquivalentTo()

We've the following structure (simplified).

public class SymbolReference
{
     public List<AttributeValue> AttributeValues { get; set; }
}

public class AttributeValue
{
    public Guid Guid { get; set; }
}

If I now use ShouldBeEquivilantTo in my tests and want to exclude the Guid property for the second element.an exception occurs, when the property expression is parsed.

clone.ShouldBeEquivalentTo(
    model,
    options => options.Excluding(o => o.AttributeValues[1].Guid));

If I use the overload in which I can define the property path as a string, then no exception occurs, but the property is not excluded. So, the test fails.

clone.ShouldBeEquivalentTo(
    model,
    options => options.Excluding(o => o.PropertyPath == "AttributeValues[1].Guid"));

Safe (expecting) navigation

Sometimes we need to navigate to something we finally want to test.

arr.Should().NotBeNull().And.Should().HaveCount(1);
arr[0].Should().NotBeNull();
arr[0].Prop.Should().Be("xyz");

What about this:

arr.Expect().Single().Expect().NotNull().Prop.Should().Be("xyz")

Allmost the same as Should(), but it yields the raw elements it first checks to be matching the criteria...

And().Equal("a", "b", "c") is not supported

var result = new string[] { "a", "b", "c" };

result.Should().Equal("a", "b", "c")   works

result.Should().Something().And().Equal("a", "b", "c") does interpret "b" and "c" as format arguments.

Equal after And should behave the same as Equal after Should

Fresh clone does not build

When running BuildRelease.bat in a fresh clone on a machine with just VS2013 installed I get:

(updated 2014.03.19)

"C:\code\fluentassertions\FluentAssertions.sln" (Rebuild target) (1) ->
"C:\code\fluentassertions\FluentAssertions.Silverlight.Specs\FluentAssertions.Silverlight.Specs.csproj" (Rebuild target) (5) ->
(CoreCompile target) ->
c:\code\fluentassertions\FluentAssertions.Net40.Specs\MethodInfoAssertionSpecs.cs(92,105): error CS0119: 'FluentAssertions.As
sertionExtensions.Should(FluentAssertions.Types.PropertyInfoSelector)' is a 'method', which is not valid in the given context [
C:\code\fluentassertions\FluentAssertions.Silverlight.Specs\FluentAssertions.Silverlight.Specs.csproj]

"C:\code\fluentassertions\FluentAssertions.sln" (Rebuild target) (1) ->
"C:\code\fluentassertions\FluentAssertions.WinRT.Specs\FluentAssertions.WinRT.Specs.csproj" (Rebuild target) (7) ->
c:\code\fluentassertions\FluentAssertions.Net40.Specs\MethodInfoAssertionSpecs.cs(92,105): error CS0119: 'FluentAssertions.As
sertionExtensions.Should(FluentAssertions.Types.PropertyInfoSelector)' is a 'method', which is not valid in the given context [
C:\code\fluentassertions\FluentAssertions.WinRT.Specs\FluentAssertions.WinRT.Specs.csproj]

"C:\code\fluentassertions\FluentAssertions.sln" (Rebuild target) (1) ->
"C:\code\fluentassertions\FluentAssertions.Net45.Specs\FluentAssertions.Net45.Specs.csproj" (Rebuild target) (9) ->
c:\code\fluentassertions\FluentAssertions.Net40.Specs\MethodInfoAssertionSpecs.cs(92,105): error CS0119: 'FluentAssertions.As
sertionExtensions.Should(FluentAssertions.Types.PropertyInfoSelector)' is a 'method', which is not valid in the given context [
C:\code\fluentassertions\FluentAssertions.Net45.Specs\FluentAssertions.Net45.Specs.csproj]

"C:\code\fluentassertions\FluentAssertions.sln" (Rebuild target) (1) ->
"C:\code\fluentassertions\FluentAssertions.WP8.Specs\FluentAssertions.WP8.Specs.csproj" (Rebuild target) (10) ->
c:\code\fluentassertions\FluentAssertions.Net40.Specs\MethodInfoAssertionSpecs.cs(92,105): error CS0119: 'FluentAssertions.As
sertionExtensions.Should(FluentAssertions.Types.PropertyInfoSelector)' is a 'method', which is not valid in the given context [
C:\code\fluentassertions\FluentAssertions.WP8.Specs\FluentAssertions.WP8.Specs.csproj]

"C:\code\fluentassertions\FluentAssertions.sln" (Rebuild target) (1) ->
"C:\code\fluentassertions\FluentAssertions.Net40.Specs\FluentAssertions.Net40.Specs.csproj" (Rebuild target) (12) ->
MethodInfoAssertionSpecs.cs(92,105): error CS0119: 'FluentAssertions.AssertionExtensions.Should(FluentAssertions.Types.Proper
tyInfoSelector)' is a 'method', which is not valid in the given context [C:\code\fluentassertions\FluentAssertions.Net40.Specs
FluentAssertions.Net40.Specs.csproj]

10 Warning(s)
5 Error(s)

If I try and build on my VS2012 machine then I get plenty of other errors about missing targets so I guess FA is now a VS2013 only solution, which is fine.


(original errors when issue was first raised on 2014.01.07)

"C:\code\fluentassertions\FluentAssertions.sln" (Rebuild target) (1) ->
"C:\code\fluentassertions\FluentAssertions.WinRT.Specs\FluentAssertions.WinRT.Specs.csproj" (Rebuild target) (10) ->
(_SignAppxPackage target) ->
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\AppxPackage\Microsoft.AppXPackage.Targets(1144,9): error APPX0105
: Cannot import the key file 'FluentAssertions.WinRT.Specs_TemporaryKey.pfx'. The key file may be password protected. To correc
t this, try to import the certificate manually into the current user's personal certificate store. [C:\code\fluentassertions\Fl
uentAssertions.WinRT.Specs\FluentAssertions.WinRT.Specs.csproj]
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\AppxPackage\Microsoft.AppXPackage.Targets(1144,9): error APPX0102
: A certificate with thumbprint 'EF62DAF1210432C81FABD9BFEF9EBAA1BE76CB29' that is specified in the project cannot be found in
the certificate store. Please specify a valid thumbprint in the project file. [C:\code\fluentassertions\FluentAssertions.WinRT.
Specs\FluentAssertions.WinRT.Specs.csproj]
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\AppxPackage\Microsoft.AppXPackage.Targets(1144,9): error APPX0107
: The certificate specified is not valid for signing. For more information about valid certificates, see http://go.microsoft.co
m/fwlink/?LinkID=241478. [C:\code\fluentassertions\FluentAssertions.WinRT.Specs\FluentAssertions.WinRT.Specs.csproj]

Switch to Portable Class Libraries

Move as much of the code into a PCL so that refactoring isn't hampered by having to update or add links to source files from an ever increasing number of framework-specific projects.

  • Plug in test framework into AssertionHelper from specific versions
  • Move ExecutionTimeAssertions back to specific versions
  • Split AssertionsExtensions.Events into PCL extensions and specific versions
  • See if we can get AttributeBasedFormatter to be PCL compatible. Otherwise make it specific and inject it in the Formatter class
  • Move BeBinarySerializable into specific versions
  • Ensure any other extension classes properly initialize the framework-specific code
  • Move over .NET 4.0 version
  • Move over .NET 4.5 version
  • Move over SL version
  • Move over Windows Phone version
  • Move over WinRT version
  • Remove all #Ifdefs from core
  • Move the NotifyPropertyChangedExtensions.eventRecordersMap field to a better place
  • Fixup Windows Phone 8 with the correct test framework
  • Drop .NET 3.5
  • Expand multiple classes per file into individual files

Add CodeContracts to avoid ugly warnings on projects where CodeContracts is enabled

We're currently using FluentAssertions in a solution for which we've started using CodeContracts.

Since there are no contracts defined for the FluentAssertion methods this causes either a lot of warnings or unnecessary Assume/Assert calls on the test code.

Will you accept a pull request that adds the contracts? Or is there a specific reason for which you don't to add them?

MethodInfoAssertions/PropertyInfoAssertions does not work properly with NotBeNull

When attempting to verify that a MethodInfo object is not null the NotBeNull() method will fail because MethodInfoAssertions doesn't actually set to the Subject property which is what ReferenceTypeAssertions uses. The same thing applies to PropertyInfoAssertions.

ex:
var actual = type.GetMethod("SomeMethod");

actual.Should().NotBeNull(); //Fails every time

Support RegEx fluent assertion

Please make RegEx fluent validation a first class citizen.
So a code like this:

Regex.IsMatch(output, @"^\d{4}-\d{2}-\d{2}$").Should().BeTrue();

Would look like this:

output.Should().MatchRegex(@"^\d{4}-\d{2}-\d{2}$");

BeCloseTo for Timespans?

Can you add BeCloseTo(expected, allowedVariation) for TimeSpan?

Example:

var stopWatch = new Stopwatch();
var expected = TimeSpan.FromMilliseconds(400);
var allowedVariation = TimeSpan.FromMilliseconds(100);

var sut = new Receiver();
stopWatch.Start();
sut.Read(400);
stopWatch.Stop();

stopWatch.Elapsed.Should().BeCloseTo(expected, allowedVariation); 

DateTimeOffset support

It would be great if FA supported DateTimeOffset in the same way it supported DateTime.

XElementAssertions.Be(expected) throws NullReferenceException when expected is 'null'

when writing the following code

[Test]
public void Test()
{
    XElement actual = null;
    XElement expected = new XElement("Root");

    actual.Should().Be(expected);
}

I get this exception

System.NullReferenceException : Object reference not set to an instance of an object.
   at FluentAssertions.Xml.XElementAssertions.Be(XElement expected, String reason, Object[] reasonArgs) in XElementAssertions.cs: line 53

I would expect an exception message similar to for example ObjectAssertions which displays expect [...] but found <null>

IDictionary.ContainsKey assertion case sensitivity issue.

[TestMethod]
public void ReproTest()
{
IDictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{"name", "name description"}
};

        //The following 2 lines assert the same and should both pass
        dictionary.ContainsKey("NaMe").Should().BeTrue(); //passes
        dictionary.Should().ContainKey("NaMe"); //fails
    }

Building solution fails

Building FluentAssertions.sln fails:

"Error
Task 'ValidateAppxManifestItems' failed. Could not find file '..\fluentassertions\FluentAssertions.WinRT.Specs\Package.appxmanifest'. FluentAssertions.WinRT.Specs"

This file is not on GitHub, but is part of the FluentAssertions.WinRT.Specs project.

BeNull and NotBeNull are broken with PropertyInfo and MethodInfo

BeNull and NotBeNull checks do not seem to work on PropertyInfo and MethodInfo. The snippet should pass, but fails with "Expected property info not to be ". A similar failure can be seen by changing the GetProperties() method to GetMethods().

[TestFixture]
public class Repo
{
    [Test]
    public void Bug()
    {
        var p = typeof(Type).GetProperties().First();
        p.Should().NotBeNull();
    }
}

Tested against the Fluent Assertions 2.1.0.0 nuget package.

BeXXX and null

Hi,

I have just started looking into this and it looks promising.

However I find it a little verbose to have to write something like:

someInstance.Should().NotBeNull.And.BeOfType<SomeType>()

in order to check the type of an instance that could potentially be null.
I mean it seems to me that simply doing the type check would implicitly mean that null is not an acceptable value.
This is actually also how BeOfType looks at it, since calling that on a null value throws an exception. However not the exception I'd expect. I would expect it to fail the assertion, with something like 'Expected instance to be of type SomeType but instance was null'.

This is most likely also true for a number of other BeXXX methods.

Rename reason argument in Be() to because.

This may sound silly, but it would allow for something like this:

messages.Count().Should().Be(1, because: "one log message was sent");

Just adds a tad more fluency to the reading. And it would make it even more clear what the argument is used for.

ShouldBeEquivalentTo incorrectly reports a cyclic reference

Given a class containing a property named 'Logbook' and also containing an ICollection of LogbookRelation objects, which also has a Logbook property.
When one of the LogbookRelations in the collection points to the same Logbook object as the one in the parent object, FA sees this as a cyclic reference.

The following code is an example of this problem:

[TestClass]
public class LogbookEntryProjectionSpecs
{
    [TestMethod]
    public void When_comparing_two_equal_objects_it_should_consider_them_equal()
    {
        //-----------------------------------------------------------------------------------------------------------
        // Arrange
        //-----------------------------------------------------------------------------------------------------------
        LogbookCode logbook = new LogbookCode(Guid.NewGuid());

        var logbookEntry = new LogbookEntryProjection()
        {
            LogbookRelations = new [] { new LogbookRelation(logbook, true) };
        };

        var equivalentLogbookEntry = new LogbookEntryProjection()
        {
            LogbookRelations = new [] { new LogbookRelation(logbook, true) };
        };

        logbookEntry.ShouldBeEquivalentTo(equivalentLogbookEntry);
    }
}

public LogbookEntryProjection()
{
    public LogbookEntryProjection()
    {
        LogbookRelations = new List<LogbookRelation>();
    }

    public virtual LogbookCode Logbook
    {
        get { return LogbookRelations.Single(x => x.IsOriginal).Logbook; }
    }

    public virtual ICollection<LogbookRelation> LogbookRelations { get; set; }
}

public class LogbookRelation
{
    public virtual LogbookCode Logbook { get; private set; }
    public virtual bool IsOriginal { get; private set; }

    public LogbookRelation(LogbookCode logbook, bool isOriginal)
    {
        Logbook = logbook;
        IsOriginal = isOriginal;
    }
}

public class LogbookCode
{
    private Guid key;

    public LogbookCode(Guid key)
    {
    }

    public Guid Key
    {
        get { return key; }
        protected set { key = value; }
    }
}

Provide reasons using lambda

Sometimes it would be handy to compose the reason message just in case of a failing assertion.
For example currently, it seems not to be possible to get a corresponding behaviour to this obviously flawed code:

customer.Should().NotBeNull("there is no matching customer, but found customer \"{0}\".", customer.FullName);

Suggestion (overload taking Func<T, string>):

customer.Should().NotBeNull(c => string.Format("there is no matching customer, but found customer \"{0}\".", c.FullName));

ShouldThrow with AggregateException is inconsistent

I have previously had success with ShouldThrow correctly finding the exception in an AggregateException. I now however have a scenario that fails.

Expected System.Data.SqlClient.SqlException, but found (aggregated) (aggregated) (aggregated) (aggregated) (aggregated) System.Data.SqlClient.SqlException with message "Batch Id not found."
     at System.Data.SqlClient.SqlCommand.<ExecuteDbDataReaderAsync>b__24(Task`1 result)
     at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
     at System.Threading.Tasks.Task.Execute()

Possibly this is related to what appears to be a deeply nested AggregateException.

Allow disabling scanning for custom formatting

Scanning the test output directory for assemblies that contain custom implementations of IValueFormatter is quite expensive. Moreover, under MSTest, each test assembly will be run in a separate AppDomain, causing the scannign to happen multiple times.

I propose to add a setting to the with the following values.

  1. None
  2. Scan
  3. Specific assembly

Remove obsolete code

Get rid of some things:

  • ComparisonMode
  • Properties comparison API
  • Anything else marked [Obsolete]

Action.ShouldNotThrow<T>().WithMessage(...)

Sometimes one runs into an exception type that uses the message to specify a wide range of different errors. An example of such an exception is

System.Data.SqlClient.SqlException.

When (integration)testing it can just so happen to be that we're only interested in one specific kind of error, for example a PRIMARY KEY violation. In this case, it would be awesome if we could test for something along the lines of

action.ShouldNotThrow<SqlException>().WithMessage("*PRIMARY KEY*");

NotBeTrue and NotBeFalse for nullable bools.

Hi,
I am using nullable bools and find I often need to test that they are not a certain value, rather than that they are a certain value. (The reason is that I am implying null to mean that the value was not explicitly set, in which case it should default back to false).

E.g.
bool? b = GetValue();
// b should be null or false

At the moment I can test IsTrue or IsFalse, but what I need is IsNotFalse and IsNotTrue (or alternatively IsTrueOrNull, and IsFalseOrNull respectively).

As an alternative, are you familiar with the Jasmine Javascript framework. It is fairly similar except they have a generic Not() operator that can be placed before any assertion. This would allow me, for instance, to say b.Should().Not().BeTrue().

Thank you for considering this enhancement.

XElement.Should().Match()

Because there are a lot more things to test than just both attributes and elements.
Currently I use something like this:

XElement.As<XNode>().Should().Match<XElement>(x => x.Name == "foo")

.ShouldThrow<T> and .ShouldThrow<T>().WithMessage throw FileNotFoundException

Hello everyone,

I'm right in the middle of unit testing my Windows Store App which I recently upgraded to be compatible with Windows 8.1. For that I've got a bunch of Windows Store Libraries which I'm testing together with NUnit 2.6.3, FluentAssertions 2.1.0.0 (the WinRT version) and FakeItEasy 1.14.0.0 - using Visual Studio 2013.

In most of my Service classes I throw ArgumentNullExceptions which I'd love to test. After Googling for a while I found a post somewhere mentioning that I should test Exceptions by wrapping the method under test inside an Action like so:

public void TestGetMatchAsyncWithEmptyMatchId()
{
    // Arrange
    var matchWorker = new MatchWorker();

    // Act
    Action action = () => matchWorker.GetMatchAsync(string.Empty);

    // Assert
    action.ShouldThrow<ArgumentException>("Expected GetMatchAsync to throw ArgumentException");
    //.WithMessage("MatchId can't be null or empty");
}

where as the method under test looks like

public async Task<Match> GetMatchAsync(string matchId)
{
    if (string.IsNullOrEmpty(matchId))
        throw new ArgumentException("MatchId can't be null or empty", "matchId");
    /* .... */
}

Now, no matter if I execute my tests via the ReSharper 8.0 Test-Runner or straight from the NUnit Test-Runner my test will fail

System.IO.FileNotFoundException : Could not load file or assembly 'Microsoft.VisualStudio.TestPlatform.UnitTestFramework, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
   at FluentAssertions.Execution.AssertionHelper.Throw(String message)
   at FluentAssertions.Execution.AssertionScope.FailWith(String failureMessage, Object[] failureArgs) in d:\Workspace\Github\FluentAssertions\FluentAssertions.Net35\Execution\AssertionScope.cs: line 168
   at FluentAssertions.Specialized.ActionAssertions.ShouldThrow(String reason, Object[] reasonArgs) in d:\Workspace\Github\FluentAssertions\FluentAssertions.Net35\Specialized\ActionAssertions.cs: line 41
   at VERSUS.Communication.Test.Worker.MatchWorkerTest.TestGetMatchAsyncWithEmptyMatchId() in MatchWorkerTest.cs: line 73

Unfortunately I could only find v12 of the Microsoft.VisualStudio.TestPlatform.UnitTestFramework.dll on my machine which FluentAssertions doesn't want to accept ;p

Speaking of .ShouldThrow<T>().WithMessage(): The assertion will fail if you throw an ArgumentException with the name of the invalid parameter. I.e.:

Will fail:

throw new ArgumentException("MatchId can't be null or empty", "matchId");

Will work:

throw new ArgumentException("MatchId can't be null or empty");

So I also tried throwing the ArgumentException in my method under test without the name of the param which unfortunately didn't work as well.

Is it possible that .ShouldThrow doesn't work properly on async/await methods? =/
Changing the Action to something like didn't work too.

Action action = async () => await matchWorker.GetMatchAsync(string.Empty);

Any help is greatly appreciated =)

You've did an awesome job with your library so far!

Cheers~

Support VS2013

Unforunately VS2013 does not support Silverlight 4 or Windows Phone 7 so this will need some decisions on platform support.

We are switching FakeItEasy from Silverlight 4 to Silverlight 5 in the next release for this very reason (FakeItEasy/FakeItEasy#218).

Also, the WinRT projects fail to load with

The imported project "C:\Program Files (x86)\MSBuild\Microsoft\WindowsXaml\v11.0\Microsoft.Windows.UI.Xaml.CSharp.targets" was not found. Confirm that the path in the declaration is correct, and that the file exists on disk. C:\code\fluentassertions\FluentAssertions.WinRT\FluentAssertions.WinRT.csproj

Windows Store 8 is still supported in VS2013 (as well as the newer Windows Store 8.1) so this probably just needs to be tweaked in the project file. On my machine which only has VS2013, the path to the file is C:\Program Files (x86)\MSBuild\Microsoft\WindowsXaml\v12.0\8.0\Microsoft.Windows.UI.Xaml.CSharp.Targets.

ShouldHave().AllProperties failed

ShouldHave().AllProperties() gives false failure when comparing nested property declared as base type.

Expected property Schedule to be

Schedule.QuarterlyRunSchedule
{
DayOffset = Last
EndDate = <2013-10-01 14:30:00>
RecurrencePattern = Quarterly
SkipNonBusinessDays = True
StartDate = <2013-09-01 14:30:00>
}, but found

Schedule.QuarterlyRunSchedule
{
DayOffset = Last
EndDate = <2013-10-01 14:30:00>
RecurrencePattern = Quarterly
SkipNonBusinessDays = True
StartDate = <2013-09-01 14:30:00>
}.

With configuration:

  • Select all declared properties
  • Exclude property UpdatedBy
  • Exclude property CreatedAt
  • Exclude property CreatedBy
  • Exclude property UpdatedAt
  • Match property by name (or throw)
  • Invoke Action when info.RuntimeType.IsSameOrInherits(System.DateTime)
  • Invoke Action when info.RuntimeType.IsSameOrInherits(System.String)
    public class ReportSchedule
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int PackageId { get; set; }
        public RunScheduleBase Schedule { get; private set; }
        public ReportTaskStatus Status { get; set; }
        public DateTime? NextRunDate { get; set; }
        public DateTime CreatedAt { get; set; }
        public DateTime UpdatedAt { get; set; }
        public string CreatedBy { get; set; }
        public string UpdatedBy { get; set; }
    }


    public abstract class RunScheduleBase
    {
        public abstract RecurrencePattern RecurrencePattern { get; }
        [XmlIgnore]
        public DateTime StartDate { get; set; }
        [XmlIgnore]
        public DateTime EndDate { get; set; }
        [XmlAttribute("skipNonBusinessDays")]
        public bool SkipNonBusinessDays { get; set; }
    }

    public class QuarterlyRunSchedule : RunScheduleBase
    {
        [XmlAttribute("dayOffset")]
        public DayOffset DayOffset { get; set; }

        public override RecurrencePattern RecurrencePattern
        {
            get { return RecurrencePattern.Quarterly; }
        }
    }

Add BeSameAs and NotBeSameAs to ReferenceTypeAssertions

I'm writing custom assertions deriving from ReferenceTypeAssertions.

I would have expected BeSameAs and NotBeSameAs being members of ReferenceTypeAssertions as these two can be asserted for every reference type as far as my knowledge goes and as far as I've seen it is implemented on any deriving class itself.

I think we could add them to ReferenceTypeAssertions and remove them from every deriving class.

Thoughts?

ShouldBeEquivalentTo does not compare fields.

It works fine on properties, but public fields are not taken into account. One can discuss whether this is a good thing or not, though ;)

Thanks for a very nice fluent api, with very few surprises.

CollectionAssertions.NotBeEquivalentTo bug

The following code:

new[] { "a", "b" }.Should().NotBeEquivalentTo(new[] { "a", "c" })

fails, while the two given collections are obviously non-equal. It seems that NotBeEquivalentTo just checks whether given collections have the same length and are intersecting.

Collection assertions do not work directly on anything but IEnumerable objects?

Using v 2.1.0.0 of fluent Assertions from NuGet with VS 2012 in a MSTest project (.Net 4.5)

The following code in my test will not compile:

    [TestMethod]
    public void TestMyCollection()
    {
        // arrange
        IEnumerable<int> myTypedList = new [] { 1, 2, 3, 4 };

        // act

        // assert
        myTypedList.Should().Contain(1);  //<-- Cannot resolve symbol "Contain"
    }

But this does compile:

    [TestMethod]
    public void TestMyCollection()
    {
        // arrange
        IEnumerable<int> myTypedList = new [] { 1, 2, 3, 4 };

        // act
        IEnumerable myEnumerable = myTypedList;

        // assert
        myEnumerable.Should().Contain(1);
    }

I understand why this is the case, but is the expected use case for executing assertions on collections in Fluent Assertions?

Migrate to VS 2013

Would be nice to migrate the VS solution to the latest and greatest Visual Studio version

How to check AggregateException with two inner exceptions?

Updating Fluent Assertions from 2.0 to 2.2 caused several Unit Tests to fail in our project. We have a method Foo() which should throw an AggregateException with two inner exceptions.

here the simplified code example:

var firstException = new Exception();
var secondException = new Exception();

// some additional assertion code
...

Action act = () => this.testee.Foo();

act.ShouldThrow<AggregateException>()
    .And.InnerExceptions.Should().Contain(new[] { firstException, secondException });

With Fluent Assertions 2.0 the above code works perfectly fine. But with Fluent Assertions 2.2 we get this error message:

Expected System.AggregateException, but found 2 (aggregated) exceptions:

System.Exception with message "Exception of type 'System.Exception' was thrown.
...

How should we check the AggregateException with Fluent Assertions 2.2 properly?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.