Skip to content

Commit

Permalink
Merge pull request #212 from Kysluss/166-try-return-result
Browse files Browse the repository at this point in the history
Add Try with result return
  • Loading branch information
altmann authored Jul 29, 2024
2 parents 91eb658 + e1c9a03 commit ae90e0b
Show file tree
Hide file tree
Showing 4 changed files with 414 additions and 57 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,21 @@ In some scenarios you want to execute an action. If this action throws an except
var result = Result.Try(() => DoSomethingCritical());
```

You can also return your own `Result` object

```csharp
var result = Result.Try(() => {
if(IsInvalid())
{
return Result.Fail("Some error");
}

int id = DoSomethingCritical();

return Result.Ok(id);
});
```

In the above example the default catchHandler is used. The behavior of the default catchHandler can be overwritten via the global Result settings (see next example). You can control how the Error object looks.

```csharp
Expand Down
178 changes: 149 additions & 29 deletions src/FluentResults.Test/ResultWithValueTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public void Bind_ToAnotherValueTypeWithFailedResult_ReturnFailedResult()
.Should()
.BeEquivalentTo("First error message");
}

[Fact]
public async Task Bind_ToAnotherValueTypeWithFailedResult_ReturnFailedResultTask()
{
Expand All @@ -309,7 +309,7 @@ public async Task Bind_ToAnotherValueTypeWithFailedResult_ReturnFailedResultTask
.Should()
.BeEquivalentTo("First error message");
}

[Fact]
public async Task Bind_ToAnotherValueTypeWithFailedResult_ReturnFailedResultValueTask()
{
Expand All @@ -324,7 +324,7 @@ public async Task Bind_ToAnotherValueTypeWithFailedResult_ReturnFailedResultValu
.Should()
.BeEquivalentTo("First error message");
}

[Fact]
public void Bind_ToResultWithFailedResult_ReturnFailedResult()
{
Expand All @@ -339,7 +339,7 @@ public void Bind_ToResultWithFailedResult_ReturnFailedResult()
.Should()
.BeEquivalentTo("First error message");
}

[Fact]
public async Task Bind_ToResultWithFailedResult_ReturnFailedResultTask()
{
Expand All @@ -354,7 +354,7 @@ public async Task Bind_ToResultWithFailedResult_ReturnFailedResultTask()
.Should()
.BeEquivalentTo("First error message");
}

[Fact]
public async Task Bind_ToResultWithFailedResult_ReturnFailedResultValueTask()
{
Expand All @@ -369,7 +369,7 @@ public async Task Bind_ToResultWithFailedResult_ReturnFailedResultValueTask()
.Should()
.BeEquivalentTo("First error message");
}

[Fact]
public void Bind_ToAnotherValueTypeWithFailedResultAndFailedTransformation_ReturnFailedResult()
{
Expand All @@ -384,7 +384,7 @@ public void Bind_ToAnotherValueTypeWithFailedResultAndFailedTransformation_Retur
.Should()
.BeEquivalentTo("Original error message");
}

[Fact]
public async Task Bind_ToAnotherValueTypeWithFailedResultAndFailedTransformation_ReturnFailedResultTask()
{
Expand All @@ -399,7 +399,7 @@ public async Task Bind_ToAnotherValueTypeWithFailedResultAndFailedTransformation
.Should()
.BeEquivalentTo("Original error message");
}

[Fact]
public async Task Bind_ToAnotherValueTypeWithFailedResultAndFailedTransformation_ReturnFailedResultValueTask()
{
Expand All @@ -414,7 +414,7 @@ public async Task Bind_ToAnotherValueTypeWithFailedResultAndFailedTransformation
.Should()
.BeEquivalentTo("Original error message");
}

[Fact]
public void Bind_ToResultWithFailedResultAndFailedTransformation_ReturnFailedResult()
{
Expand All @@ -429,7 +429,7 @@ public void Bind_ToResultWithFailedResultAndFailedTransformation_ReturnFailedRes
.Should()
.BeEquivalentTo("Original error message");
}

[Fact]
public async Task Bind_ToResultWithFailedResultAndFailedTransformation_ReturnFailedResultTask()
{
Expand All @@ -444,7 +444,7 @@ public async Task Bind_ToResultWithFailedResultAndFailedTransformation_ReturnFai
.Should()
.BeEquivalentTo("Original error message");
}

[Fact]
public async Task Bind_ToResultWithFailedResultAndFailedTransformation_ReturnFailedResultValueTask()
{
Expand All @@ -466,8 +466,8 @@ public void Bind_ToAnotherValueTypeWhichIsSuccessful_ReturnsSuccessResult()
var valueResult = Result.Ok(1).WithSuccess("An int");

// Act
var result = valueResult.Bind(n => n == 1
? "One".ToResult().WithSuccess("It is one")
var result = valueResult.Bind(n => n == 1
? "One".ToResult().WithSuccess("It is one")
: Result.Fail<string>("Only one accepted"));

// Assert
Expand All @@ -479,15 +479,15 @@ public void Bind_ToAnotherValueTypeWhichIsSuccessful_ReturnsSuccessResult()
.Should()
.BeEquivalentTo("An int", "It is one");
}

[Fact]
public async Task Bind_ToAnotherValueTypeWhichIsSuccessful_ReturnsSuccessResultTask()
{
var valueResult = Result.Ok(1).WithSuccess("An int");

// Act
var result = await valueResult.Bind(n => Task.FromResult(n == 1
? "One".ToResult().WithSuccess("It is one")
var result = await valueResult.Bind(n => Task.FromResult(n == 1
? "One".ToResult().WithSuccess("It is one")
: Result.Fail<string>("Only one accepted")));

// Assert
Expand All @@ -499,15 +499,15 @@ public async Task Bind_ToAnotherValueTypeWhichIsSuccessful_ReturnsSuccessResultT
.Should()
.BeEquivalentTo("An int", "It is one");
}

[Fact]
public async Task Bind_ToAnotherValueTypeWhichIsSuccessful_ReturnsSuccessResultValueTask()
{
var valueResult = Result.Ok(1).WithSuccess("An int");

// Act
var result = await valueResult.Bind(n => new ValueTask<Result<string>>(n == 1
? "One".ToResult().WithSuccess("It is one")
var result = await valueResult.Bind(n => new ValueTask<Result<string>>(n == 1
? "One".ToResult().WithSuccess("It is one")
: Result.Fail<string>("Only one accepted")));

// Assert
Expand All @@ -519,7 +519,7 @@ public async Task Bind_ToAnotherValueTypeWhichIsSuccessful_ReturnsSuccessResultV
.Should()
.BeEquivalentTo("An int", "It is one");
}

[Fact]
public void Bind_ToResultWhichIsSuccessful_ReturnsSuccessResult()
{
Expand All @@ -534,7 +534,7 @@ public void Bind_ToResultWhichIsSuccessful_ReturnsSuccessResult()
.Should()
.BeEquivalentTo("First number", "It is one");
}

[Fact]
public async Task Bind_ToResultWhichIsSuccessful_ReturnsSuccessResultTask()
{
Expand All @@ -549,7 +549,7 @@ public async Task Bind_ToResultWhichIsSuccessful_ReturnsSuccessResultTask()
.Should()
.BeEquivalentTo("First number", "It is one");
}

[Fact]
public async Task Bind_ToResultWhichIsSuccessful_ReturnsSuccessResultValueTask()
{
Expand All @@ -564,7 +564,7 @@ public async Task Bind_ToResultWhichIsSuccessful_ReturnsSuccessResultValueTask()
.Should()
.BeEquivalentTo("First number", "It is one");
}

[Fact]
public void Bind_ToAnotherValueTypeWhichFailedTransformation_ReturnsFailedResult()
{
Expand All @@ -580,7 +580,7 @@ public void Bind_ToAnotherValueTypeWhichFailedTransformation_ReturnsFailedResult
.Should()
.BeEquivalentTo("Only one accepted");
}

[Fact]
public async Task Bind_ToAnotherValueTypeWhichFailedTransformation_ReturnsFailedResultTask()
{
Expand All @@ -596,7 +596,7 @@ public async Task Bind_ToAnotherValueTypeWhichFailedTransformation_ReturnsFailed
.Should()
.BeEquivalentTo("Only one accepted");
}

[Fact]
public async Task Bind_ToAnotherValueTypeWhichFailedTransformation_ReturnsFailedResultValueTask()
{
Expand All @@ -612,7 +612,7 @@ public async Task Bind_ToAnotherValueTypeWhichFailedTransformation_ReturnsFailed
.Should()
.BeEquivalentTo("Only one accepted");
}

[Fact]
public void Bind_ToResultWhichFailedTransformation_ReturnsFailedResult()
{
Expand All @@ -628,7 +628,7 @@ public void Bind_ToResultWhichFailedTransformation_ReturnsFailedResult()
.Should()
.BeEquivalentTo("Only one accepted");
}

[Fact]
public async Task Bind_ToResultWhichFailedTransformation_ReturnsFailedResultTask()
{
Expand All @@ -644,7 +644,7 @@ public async Task Bind_ToResultWhichFailedTransformation_ReturnsFailedResultTask
.Should()
.BeEquivalentTo("Only one accepted");
}

[Fact]
public async Task Bind_ToResultWhichFailedTransformation_ReturnsFailedResultValueTask()
{
Expand Down Expand Up @@ -797,6 +797,126 @@ public async Task Try_execute_failed_valuetask_async_action_with_custom_catchHan
error.Message.Should().Be("xy");
}

[Fact]
public void Try_execute_failed_func_return_failed_result()
{
var error = new Error("xy");
Result<int> Action() => Result.Fail<int>(error);

var result = Result.Try(Action);

result.IsSuccess.Should().BeFalse();
result.Errors.Should().HaveCount(1);
result.Errors.First().Should().Be(error);
}

[Fact]
public async Task Try_execute_failed_func_async_return_failed_result()
{
var error = new Error("xy");
Task<Result<int>> Action() => Task.FromResult(Result.Fail<int>(error));

var result = await Result.Try(Action);

result.IsSuccess.Should().BeFalse();
result.Errors.Should().HaveCount(1);
result.Errors.First().Should().Be(error);
}

[Fact]
public async Task Try_execute_failed_valuetask_func_async_return_failed_result()
{
var error = new Error("xy");
ValueTask<Result<int>> Action() => new ValueTask<Result<int>>(Result.Fail<int>(error));

var result = await Result.Try(Action);

result.IsSuccess.Should().BeFalse();
result.Errors.Should().HaveCount(1);
result.Errors.First().Should().Be(error);
}

[Fact]
public void Try_execute_success_func_return_success_result()
{
Result<int> Action() => Result.Ok(5);

var result = Result.Try(Action);

result.IsSuccess.Should().BeTrue();
result.Value.Should().Be(5);
result.Errors.Should().BeEmpty();
}

[Fact]
public async Task Try_execute_success_func_async_return_success_result()
{
Task<Result<int>> Action() => Task.FromResult(Result.Ok(5));

var result = await Result.Try(Action);

result.IsSuccess.Should().BeTrue();
result.Value.Should().Be(5);
result.Errors.Should().BeEmpty();
}

[Fact]
public async Task Try_execute_success_valuetask_func_async_return_success_result()
{
ValueTask<Result<int>> Action() => new ValueTask<Result<int>>(Result.Ok(5));

var result = await Result.Try(Action);

result.IsSuccess.Should().BeTrue();
result.Value.Should().Be(5);
result.Errors.Should().BeEmpty();
}

[Fact]
public void Try_execute_withresult_failed_task_action_with_custom_catchHandler_return_failed_result()
{
var exception = new Exception("ex message");
Result<int> Action() => throw exception;

var result = Result.Try(Action, _ => new Error("xy"));

result.IsSuccess.Should().BeFalse();
result.Errors.Should().HaveCount(1);

var error = result.Errors.First();
error.Message.Should().Be("xy");
}

[Fact]
public async Task Try_execute_withresult_failed_task_async_action_with_custom_catchHandler_return_failed_result()
{
var exception = new Exception("ex message");
Task<Result<int>> Action() => throw exception;

var result = await Result.Try(Action, _ => new Error("xy"));

result.IsSuccess.Should().BeFalse();
result.Errors.Should().HaveCount(1);

var error = result.Errors.First();
error.Message.Should().Be("xy");
}

[Fact]
public async Task Try_execute_withresult_failed_valuetask_async_action_with_custom_catchHandler_return_failed_result()
{
var exception = new Exception("ex message");
ValueTask<Result<int>> Action() => throw exception;

var result = await Result.Try(Action, _ => new Error("xy"));

result.IsSuccess.Should().BeFalse();
result.Errors.Should().HaveCount(1);

var error = result.Errors.First();
error.Message.Should().Be("xy");
}

[Fact]
public void Implicit_conversion_T_is_converted_to_Success_result_of_T()
{
Expand Down Expand Up @@ -954,7 +1074,7 @@ private static Result<dynamic> DynamicConvert(dynamic source, Type dest)
{
var result = new Result<dynamic>();
var converted = Convert.ChangeType(source, dest);
var x = result.WithValue(converted);
var x = result.WithValue(converted);
return x;
}
}
Expand Down
Loading

0 comments on commit ae90e0b

Please sign in to comment.