Skip to content

TypeSelector.ThatAreUnderNamespace(null) behaves inconsistently and throws exceptions #1185

@kimsey0

Description

@kimsey0

Description

Issue originally reported here and in further comments: #1175 (comment)

Complete minimal example reproducing the issue

For classes:

class ClassInGlobalNamespace { }

namespace DummyNamespace {
    class ClassInDummyNamespace { }
}

And for type selectors:

var typeInGlobalNamespace = typeof(ClassInGlobalNamespace);
var typesInGlobalNamespace = new TypeSelector(typeInGlobalNamespace);

var typeInDummyNamespace = typeof(ClassInDummyNamespace);
var typesInDummyNamespace = new TypeSelector(typeInDummyNamespace);

Expected behavior:

All types are under the global namespace. No types are not under the global namespace.

typesInGlobalNamespace.ThatAreUnderNamespace(typeInGlobalNamespace.Namespace).AsEnumerable().Should().HaveCount(1);
typesInGlobalNamespace.ThatAreUnderNamespace(null).AsEnumerable().Should().HaveCount(1);

typesInGlobalNamespace.ThatAreNotUnderNamespace(typeInGlobalNamespace.Namespace).AsEnumerable().Should().HaveCount(0);
typesInGlobalNamespace.ThatAreNotUnderNamespace(null).AsEnumerable().Should().HaveCount(0);

typesInDummyNamespace.ThatAreUnderNamespace(null).AsEnumerable().Should().HaveCount(1);
typesInDummyNamespace.ThatAreNotUnderNamespace(null).AsEnumerable().Should().HaveCount(0);

Actual behavior:

Types in the global namespace are both under and not under it. The filtering methods throw exceptions when run for types not in the global namespace.

typesInGlobalNamespace.ThatAreUnderNamespace(typeInGlobalNamespace.Namespace).AsEnumerable().Should().HaveCount(0);
typesInGlobalNamespace.ThatAreUnderNamespace(null).AsEnumerable().Should().HaveCount(0);

typesInGlobalNamespace.ThatAreNotUnderNamespace(typeInGlobalNamespace.Namespace).AsEnumerable().Should().HaveCount(0);
typesInGlobalNamespace.ThatAreNotUnderNamespace(null).AsEnumerable().Should().HaveCount(0);

Action thatAreUnderNamespace = () => typesInDummyNamespace.ThatAreUnderNamespace(null);
Action thatAreNotUnderNamespace = () => typesInDummyNamespace.ThatAreNotUnderNamespace(null);
thatAreUnderNamespace.Should().Throw<ArgumentNullException>();
thatAreNotUnderNamespace.Should().Throw<ArgumentNullException>();

Versions

  • Which version of Fluent Assertions are you using?
    Newest master branch.

  • Which .NET runtime and version are you targeting? E.g. .NET framework 4.6.1 or .NET Core 2.0.
    .NET Framework 4.5, .NET Framework 4.7, .NET Core 2.0, and .NET Core 3.0.

Additional Information

Suggested fix is to change the ThatAreUnderNamespace and ThatAreNotUnderNamespace methods from:

public TypeSelector ThatAreUnderNamespace(string @namespace)
{
    types = types.Where(t.Namespace?.StartsWith(@namespace) == true).ToList();
    return this;
}

public TypeSelector ThatAreNotUnderNamespace(string @namespace)
{
    types = types.Where(t => t.Namespace?.StartsWith(@namespace) != true).ToList();
    return this;
}

to:

public TypeSelector ThatAreUnderNamespace(string @namespace)
{
    types = types.Where(t => @namespace == null || t.Namespace?.StartsWith(@namespace) == true).ToList();
    return this;
}

public TypeSelector ThatAreNotUnderNamespace(string @namespace)
{
    types = types.Where(t => @namespace != null && t.Namespace?.StartsWith(@namespace) != true).ToList();
    return this;
}

However, this would be a breaking change. There are not currently tests that run ThatAreUnderNamespace(null) or ThatAreNotUnderNamespace(null).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions