2026-03-30 12:51:19 -05:00
|
|
|
namespace StevanFreeborn.Results.Tests;
|
|
|
|
|
|
|
|
|
|
public class ResultTests
|
|
|
|
|
{
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Ok_WhenCalled_ItShouldReturnSuccessResult()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Ok<Unit, Error>(default);
|
|
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(result.IsSuccess).IsTrue();
|
|
|
|
|
await Assert.That(result.IsFailure).IsFalse();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Fail_WhenCalled_ItShouldReturnFailureResult()
|
|
|
|
|
{
|
|
|
|
|
var error = new Error("code", "message");
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Fail<Unit, Error>(error);
|
2026-03-30 17:29:41 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(result.IsSuccess).IsFalse();
|
|
|
|
|
await Assert.That(result.IsFailure).IsTrue();
|
|
|
|
|
await Assert.That(result.Error).IsEqualTo(error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
2026-03-30 15:03:01 -05:00
|
|
|
public void Error_WhenResultIsSuccess_ItShouldThrowInvalidOperationException()
|
2026-03-30 12:51:19 -05:00
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
Assert.Throws<InvalidOperationException>(() => _ = Result.Ok<Unit, Error>(default).Error);
|
2026-03-30 12:51:19 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task ImplicitConversion_FromError_ItShouldReturnFailureResult()
|
|
|
|
|
{
|
|
|
|
|
var error = new Error("code", "message");
|
|
|
|
|
Result<Unit, Error> result = error;
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(result.IsFailure).IsTrue();
|
|
|
|
|
await Assert.That(result.Error).IsEqualTo(error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Map_WhenResultIsSuccess_ItShouldInvokeAction()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Ok<Unit, Error>(default);
|
2026-03-30 12:51:19 -05:00
|
|
|
var invoked = false;
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
result.Map(_ => invoked = true);
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(invoked).IsTrue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Map_WhenResultIsFailure_ItShouldSkipAction()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Fail<Unit, Error>(new Error("code", "message"));
|
2026-03-30 12:51:19 -05:00
|
|
|
var invoked = false;
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
result.Map(_ => invoked = true);
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(invoked).IsFalse();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Map_WhenCalled_ItShouldReturnOriginalResult()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Ok<Unit, Error>(default);
|
2026-03-30 12:51:19 -05:00
|
|
|
var mapped = result.Map(_ => { });
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(mapped.IsSuccess).IsTrue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Bind_WhenResultIsSuccess_ItShouldInvokeBinder()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Ok<Unit, Error>(default);
|
|
|
|
|
var bound = result.Bind(_ => Result.Ok<Unit, Error>(default));
|
|
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(bound.IsSuccess).IsTrue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Bind_WhenResultIsFailure_ItShouldReturnOriginalResult()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Fail<Unit, Error>(new Error("code", "message"));
|
|
|
|
|
var bound = result.Bind(_ => Result.Ok<Unit, Error>(default));
|
|
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(bound.IsFailure).IsTrue();
|
|
|
|
|
await Assert.That(bound.Error).IsEqualTo(result.Error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Bind_WhenResultIsSuccess_ItShouldReturnBinderResult()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Ok<Unit, Error>(default);
|
|
|
|
|
var bound = result.Bind(_ => Result.Fail<Unit, Error>(new Error("new_error", "new message")));
|
|
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(bound.IsFailure).IsTrue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Match_WhenResultIsSuccess_ItShouldReturnOnSuccessValue()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Ok<Unit, Error>(default);
|
2026-03-30 12:51:19 -05:00
|
|
|
var matched = result.Match(_ => "success", _ => "failure");
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(matched).IsEqualTo("success");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Match_WhenResultIsFailure_ItShouldReturnOnFailureValue()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Fail<Unit, Error>(new Error("code", "message"));
|
2026-03-30 12:51:19 -05:00
|
|
|
var matched = result.Match(_ => "success", e => e.Code);
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(matched).IsEqualTo("code");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Match_WhenResultIsSuccess_ItShouldInvokeOnSuccess()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Ok<Unit, Error>(default);
|
2026-03-30 12:51:19 -05:00
|
|
|
var invoked = false;
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
result.Match(_ => invoked = true, _ => { });
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(invoked).IsTrue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Match_WhenResultIsFailure_ItShouldInvokeOnFailure()
|
|
|
|
|
{
|
|
|
|
|
var error = new Error("code", "message");
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Fail<Unit, Error>(error);
|
2026-03-30 12:51:19 -05:00
|
|
|
var invoked = false;
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
result.Match(_ => { }, e => invoked = true);
|
2026-03-30 15:03:01 -05:00
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(invoked).IsTrue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Try_WhenActionSucceeds_ItShouldReturnOk()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Try<Unit, Error>(() => default);
|
|
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(result.IsSuccess).IsTrue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Try_WhenActionThrowsException_ItShouldReturnFailWithUnexpectedError()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Try<Unit, Error>(() => throw new Exception("test error"));
|
|
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(result.IsFailure).IsTrue();
|
|
|
|
|
await Assert.That(result.Error.Code).IsEqualTo("UnexpectedError");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public async Task Try_WhenActionThrowsException_ItShouldUseCustomError()
|
|
|
|
|
{
|
2026-03-30 15:03:01 -05:00
|
|
|
var result = Result.Try<Unit, Error>(() => throw new Exception("test"), ex => new Error("custom", ex.Message));
|
|
|
|
|
|
2026-03-30 12:51:19 -05:00
|
|
|
await Assert.That(result.IsFailure).IsTrue();
|
|
|
|
|
await Assert.That(result.Error.Code).IsEqualTo("custom");
|
|
|
|
|
}
|
2026-03-30 17:29:41 -05:00
|
|
|
}
|