public async Task CreateAndSplitBillAsync_WhenGroupHasMembers_ShouldCreateBillWithEqualLoans(decimal total, int userCount) { //Arrange var sutBuilder = new BillServiceSutBuilder(); var group = sutBuilder.CreateGroupWithUsers("Test group", userCount); var loaner = group.Users.First(); A.CallTo(() => sutBuilder.GroupRepository.GetByIdAsync(group.Id)) .Returns(group); A.CallTo(() => sutBuilder.BillRepository.AddAsync(A <Bill> ._)) .ReturnsLazily((Bill bill) => bill); var createNewBill = sutBuilder.CreateNewBill("Test bill", total, group.Id, loaner.Id); var billService = sutBuilder.CreateSut(); //Act var resultBill = await billService.CreateAndSplitBillAsync(createNewBill); //Assert A.CallTo(() => sutBuilder.BillRepository.AddAsync(A <Bill> ._)) .MustHaveHappenedOnceExactly(); resultBill.Total.ShouldBe(total); resultBill.Name.ShouldBe(createNewBill.Name); resultBill.Loaner.ShouldBe(loaner); resultBill.Loans.Count.ShouldBe(group.Users.Count); var billLoanees = resultBill.Loans.Select(loan => loan.Loanee); billLoanees.ShouldBe(group.Users); var loanTotal = resultBill.Loans.Sum(loan => loan.Amount); loanTotal.ShouldBe(total); //Explanation of ToZero: https://docs.microsoft.com/en-us/dotnet/api/system.midpointrounding?view=netcore-3.1#directed-rounding var expectedAmount = Math.Round(total / userCount, 2, MidpointRounding.ToZero); resultBill.Loans.ForEach((loan) => { // Allow error of 1 cent loan.Amount.ShouldBeInRange(expectedAmount, expectedAmount + 0.01M); }); }
public void CreateAndSplitBillAsync_WhenGroupDoesNotExist_ShouldThrow() { //Arrange var sutBuilder = new BillServiceSutBuilder(); var group = sutBuilder.CreateGroupWithUsers("Test group", 0); var loaner = sutBuilder.CreateUser(); A.CallTo(() => sutBuilder.GroupRepository.GetByIdAsync(group.Id)) .Returns <Group?>(null); A.CallTo(() => sutBuilder.BillRepository.AddAsync(A <Bill> ._)) .ReturnsLazily((Bill bill) => bill); var createNewBill = sutBuilder.CreateNewBill("Test bill", 100, group.Id, loaner.Id); var billService = sutBuilder.CreateSut(); //Act & Assert var exception = Assert.ThrowsAsync <NotFoundException>(async() => await billService.CreateAndSplitBillAsync(createNewBill)); exception.Message.ShouldBe($"Group with id {group.Id} does not exist."); }
public void CreateAndSplitBillAsync_WhenBillPayeeIsNotInGroup_ShouldThrow(decimal total, int userCount) { //Arrange var sutBuilder = new BillServiceSutBuilder(); var group = sutBuilder.CreateGroupWithUsers("Test group", userCount); var loaner = sutBuilder.CreateUser(); A.CallTo(() => sutBuilder.GroupRepository.GetByIdAsync(group.Id)) .Returns(group); A.CallTo(() => sutBuilder.BillRepository.AddAsync(A <Bill> ._)) .ReturnsLazily((Bill bill) => bill); var createNewBill = sutBuilder.CreateNewBill("Test bill", total, group.Id, loaner.Id); var billService = sutBuilder.CreateSut(); //Act & Aseert var exception = Assert.ThrowsAsync <NotFoundException>(async() => await billService.CreateAndSplitBillAsync(createNewBill)); exception.Message.ShouldBe($"Payee with id {loaner.Id} does not exist in group."); }