Fluent Assertions - przyjemne asserty w testach
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class GetByIdTests : BaseTest | |
{ | |
protected Mock<IProductRepository> Repository { get; private set; } | |
protected ProductLogic Create() | |
{ | |
Repository = new Mock<IProductRepository>(); | |
return new ProductLogic(new Lazy<IProductRepository>(() => Repository.Object)); | |
} | |
[Fact] | |
public void Return_Product_From_Repository() | |
{ | |
var logic = Create(); | |
var product = Builder<Product>.CreateNew().Build(); | |
Repository.Setup(r => r.GetById(It.IsAny<int>())) | |
.Returns(product); | |
var result = logic.GetById(10); | |
Assert.NotNull(result); | |
Assert.True(result.Success); | |
Assert.Equal(product, result.Value); | |
Assert.NotNull(result.Errors); | |
Assert.Equal(0, result.Errors.Count()); | |
Repository.Verify(r => r.GetById(10), Times.Once()); | |
} | |
[Fact] | |
public void Return_Error_When_Product_Not_Exist() | |
{ | |
var logic = Create(); | |
Repository.Setup(r => r.GetById(It.IsAny<int>())) | |
.Returns((Product)null); | |
var result = logic.GetById(10); | |
Assert.NotNull(result); | |
Assert.False(result.Success); | |
Assert.Null(result.Value); | |
Assert.NotNull(result.Errors); | |
Assert.Equal(1, result.Errors.Count()); | |
var error = result.Errors.First(); | |
Assert.Equal(string.Empty, error.PropertyName); | |
Assert.Equal("Nie ma produktu o id 10.", error.Message); | |
Repository.Verify(r => r.GetById(10), Times.Once()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Fact] | |
public void Return_Product_From_Repository2() | |
{ | |
var logic = Create(); | |
var product = Builder<Product>.CreateNew().Build(); | |
Repository.Setup(r => r.GetById(It.IsAny<int>())) | |
.Returns(product); | |
var result = logic.GetById(10); | |
result.Should().NotBeNull(); | |
result.Success.Should().BeTrue(); | |
result.Value.Should().Be(product); | |
result.Errors.Should().NotBeNull(); | |
result.Errors.Count().Should().Be(0); | |
Repository.Verify(r => r.GetById(10), Times.Once()); | |
} | |
[Fact] | |
public void Return_Error_When_Product_Not_Exist2() | |
{ | |
var logic = Create(); | |
Repository.Setup(r => r.GetById(It.IsAny<int>())) | |
.Returns((Product)null); | |
var result = logic.GetById(10); | |
result.Should().NotBeNull(); | |
result.Success.Should().BeFalse(); | |
result.Value.Should().BeNull(); | |
result.Errors.Should().NotBeNull(); | |
result.Errors.Count().Should().Be(1); | |
var error = result.Errors.First(); | |
error.PropertyName.Should().BeEmpty(); | |
error.Message.Should().Be("Nie ma produktu o id 10."); | |
Repository.Verify(r => r.GetById(10), Times.Once()); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Fact] | |
public void Return_Product_From_Repository3() | |
{ | |
var logic = Create(); | |
var product = Builder<Product>.CreateNew().Build(); | |
Repository.Setup(r => r.GetById(It.IsAny<int>())) | |
.Returns(product); | |
var result = logic.GetById(10); | |
result.Should().BeSuccess(product); | |
Repository.Verify(r => r.GetById(10), Times.Once()); | |
} | |
[Fact] | |
public void Return_Error_When_Product_Not_Exist3() | |
{ | |
var logic = Create(); | |
Repository.Setup(r => r.GetById(It.IsAny<int>())) | |
.Returns((Product)null); | |
var result = logic.GetById(10); | |
result.Should().BeFailure("Nie ma produktu o id 10."); | |
Repository.Verify(r => r.GetById(10), Times.Once()); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public partial interface IProductRepository : IRepository<Product> | |
{ | |
} | |
public interface IRepository<T> where T : BaseModel, new() | |
{ | |
void Add(T entity); | |
void Delete(T entity); | |
void Delete(int id); | |
T GetById(int id); | |
IQueryable<T> GetAllActive(); | |
IQueryable<T> GetAll(); | |
void SaveChanges(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ProductLogic : IProductLogic | |
{ | |
private Lazy<IProductRepository> _repository; | |
protected IProductRepository Repository | |
{ | |
get { return _repository.Value; } | |
} | |
public ProductLogic(Lazy<IProductRepository> repository) | |
{ | |
_repository = repository; | |
} | |
public Result<Product> GetById(int id) | |
{ | |
var product = Repository.GetById(id); | |
if (product == null) | |
{ | |
return Result.Failure<Product>($"Nie ma produktu o id {id}."); | |
} | |
return Result.Ok(product); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Result | |
{ | |
public bool Success { get; set; } | |
public IEnumerable<ErrorMessage> Errors { get; set; } | |
public static Result Ok() | |
{ | |
return new Result() | |
{ | |
Success = true | |
}; | |
} | |
public static Result<T> Ok<T>(T value) | |
{ | |
return new Result<T>() | |
{ | |
Success = true, | |
Value = value, | |
Errors = new List<ErrorMessage>() | |
}; | |
} | |
public static Result<T> Failure<T>(IEnumerable<ValidationFailure> validationFailures) | |
{ | |
var result = new Result<T>(); | |
result.Success = false; | |
result.Errors = validationFailures.Select(v => new ErrorMessage() | |
{ | |
PropertyName = v.PropertyName, | |
Message = v.ErrorMessage | |
}); | |
return result; | |
} | |
public static Result<T> Failure<T>(string message) | |
{ | |
var result = new Result<T>(); | |
result.Success = false; | |
result.Errors = new List<ErrorMessage>() | |
{ | |
new ErrorMessage() | |
{ | |
PropertyName = string.Empty, | |
Message = message | |
} | |
}; | |
return result; | |
} | |
} | |
public class Result<T> : Result | |
{ | |
public T Value { get; set; } | |
} | |
public class ErrorMessage | |
{ | |
public string PropertyName { get; set; } | |
public string Message { get; set; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ResultAssertions<T> : ReferenceTypeAssertions<Result<T>, ResultAssertions<T>> | |
{ | |
public ResultAssertions(Result<T> result) | |
{ | |
Subject = result; | |
} | |
protected override string Identifier => "result"; | |
public ResultAssertions<T> BeSuccess(T value, string because = "", params object[] becauseArgs) | |
{ | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject != null) | |
.FailWith("The result can't be null."); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject.Success) | |
.FailWith("The Success should be true."); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject.Value.IsSameOrEqualTo(value)) | |
.FailWith("The Value should be the same as expected."); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject.Errors != null) | |
.FailWith("The Errors can't be null."); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject.Errors.Any() == false) | |
.FailWith("The Errors can't have any errors."); | |
return this; | |
} | |
public ResultAssertions<T> BeFailure(string property, string message, string because = "", params object[] becauseArgs) | |
{ | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject != null) | |
.FailWith("The result can't be null."); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject.Success == false) | |
.FailWith("The Success should be false."); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject.Value == null) | |
.FailWith("The Value should be null."); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject.Errors != null) | |
.FailWith("The Errors can't be null."); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(Subject.Errors.Any()) | |
.FailWith("The Errors should have errors."); | |
var error = Subject.Errors.FirstOrDefault(e => e.PropertyName == property); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(error != null) | |
.FailWith($"The Errors should contains error for property '{property}'."); | |
Execute.Assertion | |
.BecauseOf(because, becauseArgs) | |
.ForCondition(error.Message == message) | |
.FailWith($"The Message for property '{property}' should be '{message}'."); | |
return this; | |
} | |
public ResultAssertions<T> BeFailure(string message, string because = "", | |
params object[] becauseArgs) | |
{ | |
BeFailure(String.Empty, message, because, becauseArgs); | |
return this; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class ResultExtensions | |
{ | |
public static ResultAssertions<T> Should<T>(this Result<T> instance) | |
{ | |
return new ResultAssertions<T>(instance); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment