Skip to content

Commit

Permalink
Add unit tests for better coverage in Execution namespace (#2042)
Browse files Browse the repository at this point in the history
  • Loading branch information
lg2de committed Jan 21, 2023
1 parent 1f6238f commit b79a087
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 25 deletions.
7 changes: 6 additions & 1 deletion Src/FluentAssertions/Common/Configuration.cs
Expand Up @@ -5,6 +5,11 @@ namespace FluentAssertions.Common;

public class Configuration
{
/// <summary>
/// Defines the key for the configuration of the test framework to be assumed in FluentAssertions.
/// </summary>
private const string TestFrameworkConfigurationKey = "FluentAssertions.TestFramework";

#region Private Definitions

private readonly object propertiesAccessLock = new();
Expand Down Expand Up @@ -118,7 +123,7 @@ public string TestFrameworkName
{
if (string.IsNullOrEmpty(testFrameworkName))
{
testFrameworkName = store.GetSetting("FluentAssertions.TestFramework");
testFrameworkName = store.GetSetting(TestFrameworkConfigurationKey);
}

return testFrameworkName;
Expand Down
2 changes: 1 addition & 1 deletion Src/FluentAssertions/Common/Services.cs
Expand Up @@ -46,6 +46,6 @@ public static void ResetToDefaults()
#else
ConfigurationStore = new NullConfigurationStore();
#endif
ThrowException = TestFrameworkProvider.Throw;
ThrowException = new TestFrameworkProvider(Configuration).Throw;
}
}
49 changes: 28 additions & 21 deletions Src/FluentAssertions/Execution/TestFrameworkProvider.cs
Expand Up @@ -6,7 +6,10 @@

namespace FluentAssertions.Execution;

internal static class TestFrameworkProvider
/// <summary>
/// Implements a wrapper around all supported test frameworks to throw the correct assertion exception.
/// </summary>
internal class TestFrameworkProvider
{
#region Private Definitions

Expand All @@ -19,22 +22,25 @@ internal static class TestFrameworkProvider
["xunit2"] = new XUnit2TestFramework() // Keep this the last one as it uses a try/catch approach
};

private static ITestFramework testFramework;
private readonly Configuration configuration;

private ITestFramework testFramework;

#endregion

[DoesNotReturn]
public static void Throw(string message)
public TestFrameworkProvider(Configuration configuration)
{
if (testFramework is null)
{
testFramework = DetectFramework();
}
this.configuration = configuration;
}

[DoesNotReturn]
public void Throw(string message)
{
testFramework ??= DetectFramework();
testFramework.Throw(message);
}

private static ITestFramework DetectFramework()
private ITestFramework DetectFramework()
{
ITestFramework detectedFramework = AttemptToDetectUsingAppSetting()
?? AttemptToDetectUsingDynamicScanning()
Expand All @@ -43,9 +49,9 @@ private static ITestFramework DetectFramework()
return detectedFramework;
}

private static ITestFramework AttemptToDetectUsingAppSetting()
private ITestFramework AttemptToDetectUsingAppSetting()
{
string frameworkName = Services.Configuration.TestFrameworkName;
string frameworkName = configuration.TestFrameworkName;
if (string.IsNullOrEmpty(frameworkName))
{
return null;
Expand All @@ -54,22 +60,23 @@ private static ITestFramework AttemptToDetectUsingAppSetting()
if (!Frameworks.TryGetValue(frameworkName, out ITestFramework framework))
{
string frameworks = string.Join(", ", Frameworks.Keys);
var message = $"FluentAssertions was configured to use {frameworkName} but the requested test framework is not supported. " +
$"Please use one of the supported frameworks: {frameworks}";
var message = $"FluentAssertions was configured to use the test framework '{frameworkName}' but this is not supported. " +
$"Please use one of the supported frameworks: {frameworks}.";

throw new Exception(message);
throw new InvalidOperationException(message);
}

if (!framework.IsAvailable)
{
string frameworks = string.Join(", ", Frameworks.Keys);
var message = framework is LateBoundTestFramework lateBoundTestFramework
? $"FluentAssertions was configured to use {frameworkName} but the required test framework assembly {lateBoundTestFramework.AssemblyName} could not be found. " +
$"Please use one of the supported frameworks: {frameworks}"
: $"FluentAssertions was configured to use {frameworkName} but the required test framework could not be found. " +
$"Please use one of the supported frameworks: {frameworks}";

throw new Exception(message);
var innerMessage = framework is LateBoundTestFramework lateBoundTestFramework
? $"the required assembly '{lateBoundTestFramework.AssemblyName}' could not be found"
: "it could not be found";
var message =
$"FluentAssertions was configured to use the test framework '{frameworkName}' but {innerMessage}. " +
$"Please use one of the supported frameworks: {frameworks}.";

throw new InvalidOperationException(message);
}

return framework;
Expand Down
3 changes: 3 additions & 0 deletions Src/FluentAssertions/Execution/XUnit2TestFramework.cs
Expand Up @@ -4,6 +4,9 @@

namespace FluentAssertions.Execution;

/// <summary>
/// Implements the XUnit (version 2) test framework adapter.
/// </summary>
internal class XUnit2TestFramework : ITestFramework
{
private Assembly assembly;
Expand Down
4 changes: 2 additions & 2 deletions Tests/FluentAssertions.Equivalency.Specs/TypedDataSetSpecs.cs
Expand Up @@ -236,9 +236,9 @@ public void When_HasErrors_does_not_match_and_property_is_excluded_as_list_it_sh
dataSet2.TypedDataTable1.Rows[0].RowError = "Manually added error";

// Act & Assert
IEnumerable<string> excludedTales = new[] { "TypedDataTable1" };
IEnumerable<string> excludedTables = new[] { "TypedDataTable1" };
dataSet1.Should().BeEquivalentTo(dataSet2,
config => config.Excluding(dataSet => dataSet.HasErrors).ExcludingTables(excludedTales));
config => config.Excluding(dataSet => dataSet.HasErrors).ExcludingTables(excludedTables));
}

[Fact]
Expand Down
@@ -0,0 +1,24 @@
using FluentAssertions.Execution;
using Xunit;

namespace FluentAssertions.Specs.Execution;

public class FallbackTestFrameworkTests
{
[Fact]
public void The_fallback_test_framework_is_available()
{
var sut = new FallbackTestFramework();

sut.IsAvailable.Should().BeTrue();
}

[Fact]
public void Throwing_with_messages_throws_the_exception()
{
var sut = new FallbackTestFramework();

sut.Invoking(x => x.Throw("test message")).Should().ThrowExactly<AssertionFailedException>()
.WithMessage("test message");
}
}
@@ -0,0 +1,99 @@
using System;
using FluentAssertions.Common;
using FluentAssertions.Execution;
using Xunit;
using Xunit.Sdk;

namespace FluentAssertions.Specs.Execution;

public class TestFrameworkProviderTests
{
[Fact]
public void When_running_xunit_test_implicitly_it_should_be_detected()
{
// Arrange
var configuration = new Configuration(new TestConfigurationStore());
var testFrameworkProvider = new TestFrameworkProvider(configuration);

// Act
Action act = () => testFrameworkProvider.Throw("MyMessage");

// Assert
act.Should().Throw<XunitException>();
}

[Fact]
public void When_running_xunit_test_explicitly_it_should_be_detected()
{
// Arrange
var configuration = new Configuration(new TestConfigurationStore())
{
TestFrameworkName = "xunit2"
};
var testFrameworkProvider = new TestFrameworkProvider(configuration);

// Act
Action act = () => testFrameworkProvider.Throw("MyMessage");

// Assert
act.Should().Throw<XunitException>();
}

[Fact]
public void When_running_test_with_unknown_test_framework_it_should_throw()
{
// Arrange
var configuration = new Configuration(new TestConfigurationStore())
{
TestFrameworkName = "foo"
};
var testFrameworkProvider = new TestFrameworkProvider(configuration);

// Act
Action act = () => testFrameworkProvider.Throw("MyMessage");

// Assert
act.Should().Throw<InvalidOperationException>()
.WithMessage("*the test framework 'foo' but this is not supported*");
}

[Fact]
public void When_running_test_with_direct_bound_but_unavailable_test_framework_it_should_throw()
{
// Arrange
var configuration = new Configuration(new TestConfigurationStore())
{
TestFrameworkName = "nspec3"
};
var testFrameworkProvider = new TestFrameworkProvider(configuration);

// Act
Action act = () => testFrameworkProvider.Throw("MyMessage");

// Assert
act.Should().Throw<InvalidOperationException>()
.WithMessage("*test framework 'nspec3' but it could not be found*");
}

[Fact]
public void When_running_test_with_late_bound_but_unavailable_test_framework_it_should_throw()
{
// Arrange
var configuration = new Configuration(new TestConfigurationStore())
{
TestFrameworkName = "nunit"
};
var testFrameworkProvider = new TestFrameworkProvider(configuration);

// Act
Action act = () => testFrameworkProvider.Throw("MyMessage");

act.Should().Throw<InvalidOperationException>()
.WithMessage("*test framework 'nunit' but the required assembly 'nunit.framework' could not be found*");
}

private sealed class TestConfigurationStore : IConfigurationStore
{
string IConfigurationStore.GetSetting(string name) => string.Empty;
}
}

0 comments on commit b79a087

Please sign in to comment.