Skip to content

Instantly share code, notes, and snippets.

@danielplawgo
Created November 21, 2018 04:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielplawgo/32606e8f2b02f051ec6f6dd1ed4ed78e to your computer and use it in GitHub Desktop.
Save danielplawgo/32606e8f2b02f051ec6f6dd1ed4ed78e to your computer and use it in GitHub Desktop.
Fluent Assertions - przyjemne asserty w testach
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());
}
}
[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());
}
[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());
}
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();
}
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);
}
}
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; }
}
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;
}
}
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