diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/FluentResults.Extensions.AwesomeAssertions.Test.csproj b/src/FluentResults.Extensions.AwesomeAssertions.Test/FluentResults.Extensions.AwesomeAssertions.Test.csproj
new file mode 100644
index 0000000..bb668ff
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/FluentResults.Extensions.AwesomeAssertions.Test.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net48;net8.0;net9.0
+ latest
+ false
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/GlobalUsings.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/GlobalUsings.cs
new file mode 100644
index 0000000..dbacb28
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/GlobalUsings.cs
@@ -0,0 +1,4 @@
+global using System;
+global using AwesomeAssertions;
+global using Xunit;
+global using Xunit.Sdk;
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/BeFailureTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/BeFailureTests.cs
new file mode 100644
index 0000000..dd42fa7
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/BeFailureTests.cs
@@ -0,0 +1,27 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ResultTests
+{
+ public class BeFailureTests
+ {
+ [Fact]
+ public void A_failed_result_throw_no_exception()
+ {
+ var failedResult = Result.Fail("Error 1");
+
+ Action action = () => failedResult.Should().BeFailure();
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_success_result_throw_a_exception()
+ {
+ var successResult = Result.Ok();
+
+ Action action = () => successResult.Should().BeFailure();
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected result be failed, but is success");
+ }
+ }
+}
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/BeSuccessTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/BeSuccessTests.cs
new file mode 100644
index 0000000..a3e548b
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/BeSuccessTests.cs
@@ -0,0 +1,55 @@
+// ReSharper disable once CheckNamespace
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ResultTests
+{
+ public class BeSuccessTests
+ {
+ [Fact]
+ public void A_success_result_throw_no_exception()
+ {
+ var successResult = Result.Ok();
+
+ Action action = () => successResult.Should().BeSuccess();
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_failed_result_with_one_error_throw_a_exception()
+ {
+ var failedResult = Result.Fail("Error 1");
+
+ Action action = () => failedResult.Should().BeSuccess();
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected result be success, but is failed because of '{Error with Message='Error 1'}'");
+ }
+
+ [Fact]
+ public void A_failed_result_with_multiple_errors_throw_a_exception()
+ {
+ var failedResult = Result.Fail("Error 1")
+ .WithError("Error 2");
+
+ Action action = () => failedResult.Should().BeSuccess();
+
+ action.Should()
+ .Throw()
+ .WithMessage(
+ "Expected result be success, but is failed because of '{Error with Message='Error 1', Error with Message='Error 2'}'");
+ }
+
+ [Fact]
+ public void A_failed_result_with_a_success_throw_a_exception()
+ {
+ var failedResult = Result.Fail("Error 1")
+ .WithSuccess("Success 1");
+
+ Action action = () => failedResult.Should().BeSuccess();
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected result be success, but is failed because of '{Error with Message='Error 1'}'");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/HaveErrorTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/HaveErrorTests.cs
new file mode 100644
index 0000000..b7c53a7
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/HaveErrorTests.cs
@@ -0,0 +1,32 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ResultTests
+{
+ public class HaveErrorTests
+ {
+ [Theory]
+ [InlineData("Error 1")]
+ [InlineData("Error")]
+ public void A_result_with_expected_reason_throw_no_exception(string expectedError)
+ {
+ var failedResult = Result.Fail("Error 1");
+
+ Action action = () =>
+ failedResult.Should().BeFailure().And
+ .HaveError(expectedError, MessageComparisonLogics.ActualContainsExpected);
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_result_without_expected_reason_throw_a_exception()
+ {
+ var successResult = Result.Fail("Error 2");
+
+ Action action = () => successResult.Should().BeFailure().And.HaveError("Error 1");
+
+ action.Should()
+ .Throw()
+ .WithMessage(
+ "Expected result to contain error with message containing \"Error 1\", but found error '{Error with Message='Error 2'}'");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/HaveReasonTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/HaveReasonTests.cs
new file mode 100644
index 0000000..b95b998
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/HaveReasonTests.cs
@@ -0,0 +1,93 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ResultTests
+{
+ public class HaveReasonTests
+ {
+ [Theory]
+ [InlineData("Error 1")]
+ [InlineData("Error")]
+ public void A_result_with_expected_reason_throw_no_exception(string expectedError)
+ {
+ var failedResult = Result.Fail("Error 1");
+
+ Action action = () =>
+ failedResult.Should().BeFailure().And
+ .HaveReason(expectedError, MessageComparisonLogics.ActualContainsExpected);
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_result_without_expected_reason_throw_a_exception()
+ {
+ var successResult = Result.Fail("Error 2");
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason("Error 1");
+
+ action.Should()
+ .Throw()
+ .WithMessage(
+ "Expected result to contain reason with message containing \"Error 1\", but found reasons '{Error with Message='Error 2'}'");
+ }
+
+ [Theory]
+ [InlineData("Error")]
+ public void A_result_with_expected_reason_of_type_throw_no_exception_equal(string expectedError)
+ {
+ var successResult = Result.Fail(new SomeReason("Error 1"));
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason(expectedError);
+
+ action.Should().Throw();
+ }
+
+ [Theory]
+ [InlineData("Error 1")]
+ [InlineData("Error")]
+ public void A_result_with_expected_reason_of_type_throw_no_exception(string expectedError)
+ {
+ var successResult = Result.Fail(new SomeReason("Error 1"));
+
+ Action action = () =>
+ successResult.Should().BeFailure().And
+ .HaveReason(expectedError, MessageComparisonLogics.ActualContainsExpected);
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_result_without_expected_reason_of_type_throw_a_exception()
+ {
+ var successResult = Result.Fail("Error 1");
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason("Error 1");
+
+ action.Should()
+ .Throw()
+ .WithMessage(
+ "Expected result to contain reason of type \"SomeReason\" with message containing \"Error 1\", but found reasons '{Error with Message='Error 1'}'");
+ }
+
+ [Fact]
+ public void A_result_with_expected_reason_object_throw_no_exception()
+ {
+ var successResult = Result.Fail("Error 1");
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason(new Error("Error 1"));
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_result_without_expected_reason_object_throw_a_exception()
+ {
+ var successResult = Result.Fail("Error 1");
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason(new Error("Error 2"));
+
+ action.Should()
+ .Throw()
+ .WithMessage(
+ "Expected Subject.Reasons {Error with Message='Error 1'} to contain equivalent of Error with Message='Error 2'*");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/ReasonHaveMetadataTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/ReasonHaveMetadataTests.cs
new file mode 100644
index 0000000..eb7b875
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/ReasonHaveMetadataTests.cs
@@ -0,0 +1,59 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ResultTests
+{
+ public class ReasonHaveMetadataTests
+ {
+ [Fact]
+ public void A_result_with_reason_with_specific_metadata_throw_no_exception()
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ .WithMetadata("key", "value"));
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.HaveMetadata("key", "value");
+
+ action.Should().NotThrow();
+ }
+
+ [Theory]
+ [InlineData(null)]
+ [InlineData("value1")]
+ [InlineData(1)]
+ public void A_result_with_reason_with_another_metadata_because_of_value_throw_exception(object expectedMetadataValue)
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ .WithMetadata("key", "value"));
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.HaveMetadata("key", expectedMetadataValue);
+
+ action.Should()
+ .Throw()
+ .WithMessage($"Reason should contain 'key' with '{expectedMetadataValue}', but not contain it");
+ }
+
+ [Theory]
+ [InlineData("ke")]
+ [InlineData("key1")]
+ public void A_result_with_reason_with_another_metadata_because_of_key_throw_exception(string expectedMetadataKey)
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ .WithMetadata("key", "value"));
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.HaveMetadata(expectedMetadataKey, "value");
+
+ action.Should()
+ .Throw()
+ .WithMessage($"Reason should contain '{expectedMetadataKey}' with 'value', but not contain it");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/ReasonSatisfyTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/ReasonSatisfyTests.cs
new file mode 100644
index 0000000..a78cab9
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ResultTests/ReasonSatisfyTests.cs
@@ -0,0 +1,59 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ResultTests
+{
+ public class ReasonSatisfyTests
+ {
+
+ [Fact]
+ public void A_reason_with_the_expected_property_throw_no_exception()
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ {
+ Prop = "Prop1"
+ });
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.Satisfy(r => r.Prop.Should().Be("Prop1"));
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_reason_with_another_property_throw_exception()
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ {
+ Prop = "Prop1"
+ });
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.Satisfy(r => r.Prop.Should().Be("Prop2"));
+
+ action.Should()
+ .Throw();
+ }
+
+ [Fact]
+ public void A_reason_with_another_type_throw_exception()
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ {
+ Prop = "Prop1"
+ });
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.Satisfy(r => {});
+
+ action.Should()
+ .Throw();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/SomeReason.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/SomeReason.cs
new file mode 100644
index 0000000..c5ee00c
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/SomeReason.cs
@@ -0,0 +1,20 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test
+{
+ internal class SomeReason : Error
+ {
+ public string Prop { get; set; }
+
+ public SomeReason(string message) : base(message)
+ {
+
+ }
+ }
+
+ internal class AnotherReason : Error
+ {
+ public AnotherReason(string message) : base(message)
+ {
+
+ }
+ }
+}
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/BeFailureTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/BeFailureTests.cs
new file mode 100644
index 0000000..e3a3974
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/BeFailureTests.cs
@@ -0,0 +1,27 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ValueResultTests
+{
+ public class BeFailureTests
+ {
+ [Fact]
+ public void A_failed_result_throw_no_exception()
+ {
+ var failedResult = Result.Fail("Error 1");
+
+ Action action = () => failedResult.Should().BeFailure();
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_success_result_throw_a_exception()
+ {
+ var successResult = Result.Ok(1);
+
+ Action action = () => successResult.Should().BeFailure();
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected result be failed, but is success");
+ }
+ }
+}
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/BeSuccessTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/BeSuccessTests.cs
new file mode 100644
index 0000000..a14fc64
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/BeSuccessTests.cs
@@ -0,0 +1,54 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ValueResultTests
+{
+ public class BeSuccessTests
+ {
+ [Fact]
+ public void A_success_result_throw_no_exception()
+ {
+ var successResult = Result.Ok(1);
+
+ Action action = () => successResult.Should().BeSuccess();
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_failed_result_with_one_error_throw_a_exception()
+ {
+ var failedResult = Result.Fail("Error 1");
+
+ Action action = () => failedResult.Should().BeSuccess();
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected result be success, but is failed because of '{Error with Message='Error 1'}'");
+ }
+
+ [Fact]
+ public void A_failed_result_with_multiple_errors_throw_a_exception()
+ {
+ var failedResult = Result.Fail("Error 1")
+ .WithError("Error 2");
+
+ Action action = () => failedResult.Should().BeSuccess();
+
+ action.Should()
+ .Throw()
+ .WithMessage(
+ "Expected result be success, but is failed because of '{Error with Message='Error 1', Error with Message='Error 2'}'");
+ }
+
+ [Fact]
+ public void A_failed_result_with_a_success_throw_a_exception()
+ {
+ var failedResult = Result.Fail("Error 1")
+ .WithSuccess("Success 1");
+
+ Action action = () => failedResult.Should().BeSuccess();
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected result be success, but is failed because of '{Error with Message='Error 1'}'");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/HaveReasonTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/HaveReasonTests.cs
new file mode 100644
index 0000000..220e1a3
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/HaveReasonTests.cs
@@ -0,0 +1,75 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ValueResultTests
+{
+ public class HaveReasonTests
+ {
+ [Theory]
+ [InlineData("Error 1")]
+ [InlineData("Error")]
+ public void A_result_with_expected_reason_throw_no_exception(string expectedError)
+ {
+ var failedResult = Result.Fail("Error 1");
+
+ Action action = () => failedResult.Should().BeFailure().And.HaveReason(expectedError, MessageComparisonLogics.ActualContainsExpected);
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_result_without_expected_reason_throw_a_exception()
+ {
+ var successResult = Result.Fail("Error 2");
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason("Error 1");
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected result to contain reason with message containing \"Error 1\", but found reasons '{Error with Message='Error 2'}'");
+ }
+
+ [Theory]
+ [InlineData("Error 1")]
+ [InlineData("Error")]
+ public void A_result_with_expected_reason_of_type_throw_no_exception(string expectedError)
+ {
+ var successResult = Result.Fail(new SomeReason("Error 1"));
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason(expectedError, MessageComparisonLogics.ActualContainsExpected);
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_result_without_expected_reason_of_type_throw_a_exception()
+ {
+ var successResult = Result.Fail("Error 1");
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason("Error 1");
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected result to contain reason of type \"SomeReason\" with message containing \"Error 1\", but found reasons '{Error with Message='Error 1'}'");
+ }
+
+ [Fact]
+ public void A_result_with_expected_reason_object_throw_no_exception()
+ {
+ var successResult = Result.Fail("Error 1");
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason(new Error("Error 1"));
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_result_without_expected_reason_object_throw_a_exception()
+ {
+ var successResult = Result.Fail("Error 1");
+
+ Action action = () => successResult.Should().BeFailure().And.HaveReason(new Error("Error 2"));
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected Subject.Reasons {Error with Message='Error 1'} to contain equivalent of Error with Message='Error 2'*");
+ }
+ }
+}
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/HaveValueTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/HaveValueTests.cs
new file mode 100644
index 0000000..6e13618
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/HaveValueTests.cs
@@ -0,0 +1,78 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ValueResultTests
+{
+ public class HaveValueTests
+ {
+ [Fact]
+ public void Asserting_the_correct_value_of_a_success_result_throw_no_exception()
+ {
+ var successResult = Result.Ok(1);
+
+ Action action = () => successResult.Should().HaveValue(1);
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void Asserting_a_false_value_of_a_success_result_throw_a_exception()
+ {
+ var successResult = Result.Ok(1);
+
+ Action action = () => successResult.Should().HaveValue(2);
+
+ action.Should()
+ .Throw()
+ .WithMessage("Expected value is '2', but is '1'");
+ }
+
+ [Fact]
+ public void A_failed_result_throw_no_exception()
+ {
+ var failedResult = Result.Fail("Error 1");
+
+ Action action = () => failedResult.Should().HaveValue(1);
+
+ action.Should()
+ .Throw()
+ .WithMessage(
+ "Value can not be asserted because result is failed because of '{Error with Message='Error 1'}'");
+ }
+
+ [Fact]
+ public void Asserting_null_should_not_throw_exceptions_when_type_is_a_primitive()
+ {
+ var successResult = Result.Ok(null as int?);
+
+ Action action = () => successResult.Should().HaveValue(null);
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void Asserting_null_should_not_throw_exceptions_when_type_is_a_struct()
+ {
+ var successResult = Result.Ok(null as SomeStruct?);
+
+ Action action = () => successResult.Should().HaveValue(null);
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void Asserting_null_should_not_throw_exceptions_when_type_is_a_class()
+ {
+ var successResult = Result.Ok(null as SomeClass);
+
+ Action action = () => successResult.Should().HaveValue(null);
+
+ action.Should().NotThrow();
+ }
+
+ internal struct SomeStruct
+ {
+ }
+
+ internal class SomeClass
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/ReasonHaveMetadataTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/ReasonHaveMetadataTests.cs
new file mode 100644
index 0000000..6d93088
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/ReasonHaveMetadataTests.cs
@@ -0,0 +1,59 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ValueResultTests
+{
+ public class ReasonHaveMetadataTests
+ {
+ [Fact]
+ public void A_result_with_reason_with_specific_metadata_throw_no_exception()
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ .WithMetadata("key", "value"));
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.HaveMetadata("key", "value");
+
+ action.Should().NotThrow();
+ }
+
+ [Theory]
+ [InlineData(null)]
+ [InlineData("value1")]
+ [InlineData(1)]
+ public void A_result_with_reason_with_another_metadata_because_of_value_throw_exception(object expectedMetadataValue)
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ .WithMetadata("key", "value"));
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.HaveMetadata("key", expectedMetadataValue);
+
+ action.Should()
+ .Throw()
+ .WithMessage($"Reason should contain 'key' with '{expectedMetadataValue}', but not contain it");
+ }
+
+ [Theory]
+ [InlineData("ke")]
+ [InlineData("key1")]
+ public void A_result_with_reason_with_another_metadata_because_of_key_throw_exception(string expectedMetadataKey)
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ .WithMetadata("key", "value"));
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.HaveMetadata(expectedMetadataKey, "value");
+
+ action.Should()
+ .Throw()
+ .WithMessage($"Reason should contain '{expectedMetadataKey}' with 'value', but not contain it");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/ReasonSatisfyTests.cs b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/ReasonSatisfyTests.cs
new file mode 100644
index 0000000..714a84c
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions.Test/ValueResultTests/ReasonSatisfyTests.cs
@@ -0,0 +1,59 @@
+namespace FluentResults.Extensions.AwesomeAssertions.Test.ValueResultTests
+{
+ public class ReasonSatisfyTests
+ {
+
+ [Fact]
+ public void A_reason_with_the_expected_property_throw_no_exception()
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ {
+ Prop = "Prop1"
+ });
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.Satisfy(r => r.Prop.Should().Be("Prop1"));
+
+ action.Should().NotThrow();
+ }
+
+ [Fact]
+ public void A_reason_with_another_property_throw_exception()
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ {
+ Prop = "Prop1"
+ });
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.Satisfy(r => r.Prop.Should().Be("Prop2"));
+
+ action.Should()
+ .Throw();
+ }
+
+ [Fact]
+ public void A_reason_with_another_type_throw_exception()
+ {
+ var failedResult = Result.Fail(new SomeReason("Error 1")
+ {
+ Prop = "Prop1"
+ });
+
+ Action action = () => failedResult
+ .Should()
+ .BeFailure()
+ .And.HaveReason("Error 1")
+ .That.Satisfy(r => {});
+
+ action.Should()
+ .Throw();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/AndWhichThatConstraint.cs b/src/FluentResults.Extensions.AwesomeAssertions/AndWhichThatConstraint.cs
new file mode 100644
index 0000000..c8ef5e3
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/AndWhichThatConstraint.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using AwesomeAssertions;
+
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ public class AndWhichThatConstraint : AndWhichConstraint
+ {
+ public AndWhichThatConstraint(TParentConstraint parentConstraint, TMatchedElement matchedConstraint, TThatConstraint thatConstraint)
+ : base(parentConstraint, matchedConstraint)
+ {
+ That = thatConstraint;
+ }
+
+ public AndWhichThatConstraint(TParentConstraint parentConstraint, TMatchedElement matchedConstraint, IEnumerable matchedElements)
+ : base(parentConstraint, matchedConstraint)
+ {
+ }
+
+ public TThatConstraint That { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/Assertions/AssertionOperators.cs b/src/FluentResults.Extensions.AwesomeAssertions/Assertions/AssertionOperators.cs
new file mode 100644
index 0000000..cae1a9b
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/Assertions/AssertionOperators.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Linq;
+using AwesomeAssertions;
+using AwesomeAssertions.Execution;
+
+// ReSharper disable once CheckNamespace
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ internal class BeFailureAssertionOperator
+ {
+ public AndWhichConstraint Do(TResult subject, TResultAssertion parentConstraint, AssertionChain assertionChain, string because, params object[] becauseArgs)
+ where TResult : ResultBase
+ {
+ assertionChain
+ .BecauseOf(because, becauseArgs)
+ .Given(() => subject.IsFailed)
+ .ForCondition(isFailed => isFailed)
+ .FailWith("Expected result be failed, but is success");
+
+ return new AndWhichConstraint(parentConstraint, subject);
+ }
+ }
+
+ internal class BeSuccessAssertionOperator
+ {
+ public AndWhichConstraint Do(TResult subject, TResultAssertion parentConstraint, AssertionChain assertionChain, string because, params object[] becauseArgs)
+ where TResult : ResultBase
+ {
+ assertionChain
+ .BecauseOf(because, becauseArgs)
+ .Given(() => subject.IsSuccess)
+ .ForCondition(isSuccess => isSuccess)
+ .FailWith("Expected result be success, but is failed because of '{0}'", subject.Errors);
+
+ return new AndWhichConstraint(parentConstraint, subject);
+ }
+ }
+
+ internal class HaveReasonAssertionOperator
+ {
+ public AndWhichThatConstraint Do(TResult subject, TResultAssertion parentConstraint, AssertionChain assertionChain, string expectedMessage, Func messageComparison, string because, params object[] becauseArgs)
+ where TResult : ResultBase
+ {
+ messageComparison = messageComparison ?? FluentResultAssertionsConfig.MessageComparison;
+
+ assertionChain
+ .BecauseOf(because, becauseArgs)
+ .Given(() => subject.Reasons)
+ .ForCondition(reasons => reasons.Any(reason => messageComparison(reason.Message, expectedMessage)))
+ .FailWith("Expected result to contain reason with message containing {0}, but found reasons '{1}'", expectedMessage, subject.Reasons);
+
+ return new AndWhichThatConstraint(parentConstraint, subject, new ReasonAssertions(subject.Reasons.SingleOrDefault(reason => messageComparison(reason.Message, expectedMessage)), assertionChain));
+ }
+ }
+
+ internal class HaveErrorAssertionOperator
+ {
+ public AndWhichThatConstraint Do(TResult subject, TResultAssertion parentConstraint, AssertionChain assertionChain, string expectedMessage, Func messageComparison, string because, params object[] becauseArgs)
+ where TResult : ResultBase
+ {
+ messageComparison = messageComparison ?? FluentResultAssertionsConfig.MessageComparison;
+
+ assertionChain
+ .BecauseOf(because, becauseArgs)
+ .Given(() => subject.Errors)
+ .ForCondition(errors => errors.Any(reason => messageComparison(reason.Message, expectedMessage)))
+ .FailWith("Expected result to contain error with message containing {0}, but found error '{1}'", expectedMessage, subject.Errors);
+
+ return new AndWhichThatConstraint(parentConstraint, subject, new ReasonAssertions(subject.Reasons.SingleOrDefault(reason => messageComparison(reason.Message, expectedMessage)), assertionChain));
+ }
+ }
+
+ internal class HaveReasonTAssertionOperator
+ {
+ public AndWhichThatConstraint Do(TResult subject, TResultAssertion parentConstraint, AssertionChain assertionChain, string expectedMessage, Func messageComparison, string because, params object[] becauseArgs)
+ where TResult : ResultBase
+ where TReason : IReason
+ {
+ messageComparison = messageComparison ?? FluentResultAssertionsConfig.MessageComparison;
+
+ assertionChain
+ .BecauseOf(because, becauseArgs)
+ .Given(() => subject.Reasons.OfType())
+ .ForCondition(reasons => reasons.Any(reason => messageComparison(reason.Message, expectedMessage)))
+ .FailWith("Expected result to contain reason of type {0} with message containing {1}, but found reasons '{2}'", typeof(TReason).Name, expectedMessage, subject.Reasons);
+
+ return new AndWhichThatConstraint(parentConstraint, subject, new ReasonAssertions(subject.Reasons.SingleOrDefault(reason => messageComparison(reason.Message, expectedMessage)), assertionChain));
+ }
+ }
+
+ internal class HaveValueAssertionOperator
+ {
+ public AndConstraint Do(Result subject, TResultAssertion parentConstraint, AssertionChain assertionChain, T expectedValue, string because, params object[] becauseArgs)
+ {
+ assertionChain
+ .BecauseOf(because)
+ .ForCondition(subject.IsSuccess)
+ .FailWith("Value can not be asserted because result is failed because of '{0}'", subject.Errors)
+ .Then
+ .Given(() => subject.Value)
+ .ForCondition(actualValue => (actualValue == null && expectedValue == null) || actualValue.Equals(expectedValue))
+ .FailWith("Expected value is '{0}', but is '{1}'", expectedValue, subject.Value);
+
+ return new AndConstraint(parentConstraint);
+ }
+ }
+}
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/Assertions/ReasonAssertions.cs b/src/FluentResults.Extensions.AwesomeAssertions/Assertions/ReasonAssertions.cs
new file mode 100644
index 0000000..ab9f2c9
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/Assertions/ReasonAssertions.cs
@@ -0,0 +1,46 @@
+using System;
+using AwesomeAssertions;
+using AwesomeAssertions.Execution;
+using AwesomeAssertions.Primitives;
+
+// ReSharper disable once CheckNamespace
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ public class ReasonAssertions : ReferenceTypeAssertions
+ {
+ public ReasonAssertions(IReason subject, AssertionChain assertionChain)
+ : base(subject, assertionChain)
+ { }
+
+ protected override string Identifier => nameof(IReason);
+
+ public AndWhichConstraint HaveMetadata(string metadataKey, object metadataValue, string because = "", params object[] becauseArgs)
+ {
+ CurrentAssertionChain
+ .BecauseOf(because, becauseArgs)
+ .Given(() => Subject.Metadata)
+ .ForCondition(metadata =>
+ {
+ metadata.TryGetValue(metadataKey, out var actualMetadataValue);
+ return Equals(actualMetadataValue, metadataValue);
+ })
+ .FailWith($"Reason should contain '{metadataKey}' with '{metadataValue}', but not contain it");
+
+ return new AndWhichConstraint(this, Subject);
+ }
+
+ public AndWhichConstraint Satisfy(Action action) where TReason : class, IReason
+ {
+ var specificReason = Subject as TReason;
+
+ CurrentAssertionChain
+ .Given(() => Subject)
+ .ForCondition(reason => reason is TReason)
+ .FailWith($"Reason should be of type '{typeof(TReason)}', but is of type '{Subject.GetType()}'");
+
+ action(specificReason);
+
+ return new AndWhichConstraint(this, Subject);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/Assertions/ResultAssertions.cs b/src/FluentResults.Extensions.AwesomeAssertions/Assertions/ResultAssertions.cs
new file mode 100644
index 0000000..351dbc9
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/Assertions/ResultAssertions.cs
@@ -0,0 +1,121 @@
+using System;
+using AwesomeAssertions;
+using AwesomeAssertions.Execution;
+using AwesomeAssertions.Primitives;
+
+// ReSharper disable once CheckNamespace
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ public class ResultAssertions : ReferenceTypeAssertions
+ {
+ static ResultAssertions()
+ {
+ ResultFormatters.Register();
+ }
+
+ public ResultAssertions(Result subject, AssertionChain assertionChain)
+ : base(subject, assertionChain)
+ {
+ }
+
+ protected override string Identifier => nameof(Result);
+
+ public AndWhichConstraint BeFailure(string because = "", params object[] becauseArgs)
+ {
+ return new BeFailureAssertionOperator().Do(Subject, this, CurrentAssertionChain, because, becauseArgs);
+ }
+
+ public AndWhichConstraint BeSuccess(string because = "", params object[] becauseArgs)
+ {
+ return new BeSuccessAssertionOperator().Do(Subject, this, CurrentAssertionChain, because, becauseArgs);
+ }
+
+ public AndWhichThatConstraint HaveReason(string message, Func messageComparison = null, string because = "", params object[] becauseArgs)
+ {
+ return new HaveReasonAssertionOperator().Do(Subject, this, CurrentAssertionChain, message, messageComparison, because, becauseArgs);
+ }
+
+ public AndWhichThatConstraint HaveReason(string message, Func messageComparison = null, string because = "", params object[] becauseArgs) where TReason : IReason
+ {
+ return new HaveReasonTAssertionOperator().Do(Subject, this, CurrentAssertionChain, message, messageComparison, because, becauseArgs);
+ }
+
+ public AndWhichThatConstraint HaveError(string message, Func messageComparison = null, string because = "", params object[] becauseArgs)
+ {
+ return new HaveErrorAssertionOperator().Do(Subject, this, CurrentAssertionChain, message, messageComparison, because, becauseArgs);
+ }
+
+ public AndWhichConstraint HaveReason(IReason reason, string because = "", params object[] becauseArgs)
+ {
+ Subject.Reasons.Should().ContainEquivalentOf(reason, because, becauseArgs);
+
+ return new AndWhichConstraint(this, Subject);
+ }
+
+ public AndConstraint Satisfy(Action action)
+ {
+ action(Subject);
+
+ return new AndConstraint(this);
+ }
+ }
+
+ public class ResultAssertions : ReferenceTypeAssertions, ResultAssertions>
+ {
+ static ResultAssertions()
+ {
+ ResultFormatters.Register();
+ }
+
+ public ResultAssertions(Result subject, AssertionChain assertionChain)
+ : base(subject, assertionChain)
+ {
+ }
+
+ protected override string Identifier => nameof(Result);
+
+ public AndWhichConstraint, Result> BeFailure(string because = "", params object[] becauseArgs)
+ {
+ return new BeFailureAssertionOperator().Do(Subject, this, CurrentAssertionChain, because, becauseArgs);
+ }
+
+ public AndWhichConstraint, Result> BeSuccess(string because = "", params object[] becauseArgs)
+ {
+ return new BeSuccessAssertionOperator().Do(Subject, this, CurrentAssertionChain, because, becauseArgs);
+ }
+
+ public AndWhichThatConstraint, Result, ReasonAssertions> HaveReason(string message, Func messageComparison = null, string because = "", params object[] becauseArgs)
+ {
+ return new HaveReasonAssertionOperator().Do(Subject, this, CurrentAssertionChain, message, messageComparison, because, becauseArgs);
+ }
+
+ public AndWhichThatConstraint, Result, ReasonAssertions> HaveReason(string message, Func messageComparison = null, string because = "", params object[] becauseArgs) where TReason : IReason
+ {
+ return new HaveReasonTAssertionOperator().Do, Result, TReason>(Subject, this, CurrentAssertionChain, message, messageComparison, because, becauseArgs);
+ }
+
+ public AndWhichThatConstraint, Result, ReasonAssertions> HaveError(string message, Func messageComparison = null, string because = "", params object[] becauseArgs)
+ {
+ return new HaveErrorAssertionOperator().Do(Subject, this, CurrentAssertionChain, message, messageComparison, because, becauseArgs);
+ }
+
+ public AndWhichConstraint, Result> HaveReason(IReason reason, string because = "", params object[] becauseArgs)
+ {
+ Subject.Reasons.Should().ContainEquivalentOf(reason, because, becauseArgs);
+
+ return new AndWhichConstraint, Result>(this, Subject);
+ }
+
+ public AndConstraint> HaveValue(T expectedValue, string because = "", params object[] becauseArgs)
+ {
+ return new HaveValueAssertionOperator().Do(Subject, this, CurrentAssertionChain, expectedValue, because, becauseArgs);
+ }
+
+ public AndConstraint> Satisfy(Action> action)
+ {
+ action(Subject);
+
+ return new AndConstraint>(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/Common/ErrorListValueFormatter.cs b/src/FluentResults.Extensions.AwesomeAssertions/Common/ErrorListValueFormatter.cs
new file mode 100644
index 0000000..ac85ac5
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/Common/ErrorListValueFormatter.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using System.Linq;
+using AwesomeAssertions.Formatting;
+
+// ReSharper disable once CheckNamespace
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ public class ErrorListValueFormatter : IValueFormatter
+ {
+ public bool CanHandle(object value)
+ {
+ return value is List;
+ }
+
+ public void Format(object value, FormattedObjectGraph formattedGraph, FormattingContext context, FormatChild formatChild)
+ {
+ var errors = (IEnumerable)value;
+ formattedGraph.AddFragment(string.Join("; ", errors.Select(error => error.Message)));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/Common/FluentResultAssertionsConfig.cs b/src/FluentResults.Extensions.AwesomeAssertions/Common/FluentResultAssertionsConfig.cs
new file mode 100644
index 0000000..b3d5a42
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/Common/FluentResultAssertionsConfig.cs
@@ -0,0 +1,10 @@
+using System;
+
+// ReSharper disable once CheckNamespace
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ public static class FluentResultAssertionsConfig
+ {
+ public static Func MessageComparison { get; set; } = MessageComparisonLogics.Equal;
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/Common/MessageComparisonLogics.cs b/src/FluentResults.Extensions.AwesomeAssertions/Common/MessageComparisonLogics.cs
new file mode 100644
index 0000000..746e92b
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/Common/MessageComparisonLogics.cs
@@ -0,0 +1,11 @@
+using System;
+
+// ReSharper disable once CheckNamespace
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ public static class MessageComparisonLogics
+ {
+ public static Func Equal = (actual, expected) => actual == expected;
+ public static Func ActualContainsExpected = (actual, expected) => actual.Contains(expected);
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/Common/ResultFormatters.cs b/src/FluentResults.Extensions.AwesomeAssertions/Common/ResultFormatters.cs
new file mode 100644
index 0000000..7f8ee82
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/Common/ResultFormatters.cs
@@ -0,0 +1,13 @@
+using AwesomeAssertions.Formatting;
+
+// ReSharper disable once CheckNamespace
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ public static class ResultFormatters
+ {
+ public static void Register()
+ {
+ Formatter.AddFormatter(new ErrorListValueFormatter());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/FluentResults.Extensions.AwesomeAssertions.csproj b/src/FluentResults.Extensions.AwesomeAssertions/FluentResults.Extensions.AwesomeAssertions.csproj
new file mode 100644
index 0000000..c7bbfc9
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/FluentResults.Extensions.AwesomeAssertions.csproj
@@ -0,0 +1,36 @@
+
+
+
+ netstandard2.0;netstandard2.1;net8.0;net9.0
+ FluentResults.Extensions.AwesomeAssertions
+ 2.2.1.0
+ Michael Altmann
+ Asserting FluentResults objects with AwesomeAssertions
+ false
+ MIT
+
+
+ Copyright 2025 (c) Michael Altmann. All rights reserved.
+ Result Results exception error handling FluentResults
+ https://github.com/altmann/FluentResults
+ https://raw.githubusercontent.com/altmann/FluentResults/master/resources/icons/FluentResults-Icon-128.png
+ FluentResults-Icon-128.png
+
+
+ true
+ true
+ true
+ snupkg
+ false
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/ReasonExtensions.cs b/src/FluentResults.Extensions.AwesomeAssertions/ReasonExtensions.cs
new file mode 100644
index 0000000..9636785
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/ReasonExtensions.cs
@@ -0,0 +1,14 @@
+using System;
+using AwesomeAssertions.Execution;
+
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ public static class ReasonExtensions
+ {
+ public static ReasonAssertions Should(this IReason reason)
+ {
+ if (reason == null) throw new ArgumentNullException(nameof(reason));
+ return new ReasonAssertions(reason, AssertionChain.GetOrCreate());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.Extensions.AwesomeAssertions/ResultExtensions.cs b/src/FluentResults.Extensions.AwesomeAssertions/ResultExtensions.cs
new file mode 100644
index 0000000..19b7162
--- /dev/null
+++ b/src/FluentResults.Extensions.AwesomeAssertions/ResultExtensions.cs
@@ -0,0 +1,20 @@
+using System;
+using AwesomeAssertions.Execution;
+
+namespace FluentResults.Extensions.AwesomeAssertions
+{
+ public static class ResultExtensions
+ {
+ public static ResultAssertions Should(this Result value)
+ {
+ if (value == null) throw new ArgumentNullException(nameof(value));
+ return new ResultAssertions(value, AssertionChain.GetOrCreate());
+ }
+
+ public static ResultAssertions Should(this Result value)
+ {
+ if (value == null) throw new ArgumentNullException(nameof(value));
+ return new ResultAssertions(value, AssertionChain.GetOrCreate());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FluentResults.sln b/src/FluentResults.sln
index b7b7846..4d3a01e 100644
--- a/src/FluentResults.sln
+++ b/src/FluentResults.sln
@@ -26,6 +26,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentResults.Extensions.As
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentResults.Samples.WebHost", "FluentResults.Samples.WebHost\FluentResults.Samples.WebHost.csproj", "{47A242AF-DB1A-4E2C-A1BE-E3C2840BD9F5}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentResults.Extensions.AwesomeAssertions.Test", "FluentResults.Extensions.AwesomeAssertions.Test\FluentResults.Extensions.AwesomeAssertions.Test.csproj", "{7A0052F0-AAC2-D45E-B7DF-1B277D36778C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentResults.Extensions.AwesomeAssertions", "FluentResults.Extensions.AwesomeAssertions\FluentResults.Extensions.AwesomeAssertions.csproj", "{9657E8E2-6B45-58FF-0FD3-CC71E9CD3D26}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -64,6 +68,14 @@ Global
{47A242AF-DB1A-4E2C-A1BE-E3C2840BD9F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47A242AF-DB1A-4E2C-A1BE-E3C2840BD9F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47A242AF-DB1A-4E2C-A1BE-E3C2840BD9F5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7A0052F0-AAC2-D45E-B7DF-1B277D36778C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7A0052F0-AAC2-D45E-B7DF-1B277D36778C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7A0052F0-AAC2-D45E-B7DF-1B277D36778C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7A0052F0-AAC2-D45E-B7DF-1B277D36778C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9657E8E2-6B45-58FF-0FD3-CC71E9CD3D26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9657E8E2-6B45-58FF-0FD3-CC71E9CD3D26}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9657E8E2-6B45-58FF-0FD3-CC71E9CD3D26}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9657E8E2-6B45-58FF-0FD3-CC71E9CD3D26}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE