Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace Tax
- {
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Moq;
- using NUnit.Framework;
- public interface ITaxBracket
- {
- decimal CalculateTax(decimal income);
- }
- public class TaxBracket : ITaxBracket
- {
- public TaxBracket(decimal lowerBound, decimal upperBound, decimal taxRate)
- {
- if(lowerBound < 0 || upperBound < 0 || taxRate < 0)
- throw new ArgumentOutOfRangeException("lowerBound", "The lower bound should be non-negative.");
- if (lowerBound < 0 || upperBound < 0 || taxRate < 0)
- throw new ArgumentOutOfRangeException("upperBound", "The upper bound should be non-negative.");
- if (lowerBound < 0 || upperBound < 0 || taxRate < 0)
- throw new ArgumentOutOfRangeException("taxRate", "The tax rate should be non-negative.");
- if(upperBound <= lowerBound)
- throw new ArgumentException("The upper bound of the tax bracket should be non-negative.");
- this.lowerBound = lowerBound;
- this.upperBound = upperBound;
- this.taxRate = taxRate;
- }
- readonly decimal lowerBound, upperBound, taxRate;
- public decimal CalculateTax(decimal income)
- {
- if (income < 0)
- throw new ArgumentOutOfRangeException("income", "Income should be non-negative.");
- if (lowerBound > income) return 0;
- var taxable = Math.Min(income - lowerBound, upperBound - lowerBound);
- return taxable * (taxRate/100);
- }
- #if DEBUG
- [TestFixture]
- class TaxBracketTests
- {
- [Test]
- public void Constructor_CorrectParameters_ConstructsCorrectObject()
- {
- var lowerBound = 1m;
- var upperBound = 2m;
- var taxRate = 1m;
- var taxBracket = new TaxBracket(lowerBound, upperBound, taxRate);
- Assert.AreEqual(lowerBound, taxBracket.lowerBound);
- Assert.AreEqual(upperBound, taxBracket.upperBound);
- Assert.AreEqual(taxRate, taxBracket.taxRate);
- }
- [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
- public void Constructor_LowerBoundIsNegative_Throws()
- {
- new TaxBracket(-1m, 1m, 1m);
- }
- [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
- public void Constructor_UpperBoundIsNegative_Throws()
- {
- new TaxBracket(1m, -1m, 1m);
- }
- [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
- public void Constructor_TaxRateIsNegative_Throws()
- {
- new TaxBracket(1m, 1m, -1m);
- }
- [Test, ExpectedException(typeof(ArgumentException))]
- public void Constructor_LowerBoundGreaterThenUpperBound_Throws()
- {
- new TaxBracket(2m, 1m, 1m);
- }
- [Test, ExpectedException(typeof(ArgumentException))]
- public void Constructor_LowerBoundEqualsUpperBound_Throws()
- {
- new TaxBracket(1m, 1m, 1m);
- }
- [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
- public void CalculateTax_IncomeIsNegative_Throws()
- {
- var taxBracket = new TaxBracket(1m, 2m, 100);
- var tax = taxBracket.CalculateTax(-5m);
- Assert.AreEqual(tax, 0m);
- }
- [Test]
- public void CalculateTax_IncomeIsBetweenLowerAndUpperBound_CorrectTax()
- {
- var taxBracket = new TaxBracket(10m, 20m, 100);
- var tax = taxBracket.CalculateTax(50m);
- Assert.AreEqual(tax, 10m);
- }
- [Test]
- public void CalculateTax_LowerBoundIsZeroAndIncomeEqualsUpperBound_CorrectTax()
- {
- var taxBracket = new TaxBracket(0m, 1m, 100);
- var tax = taxBracket.CalculateTax(2m);
- Assert.AreEqual(tax,1m);
- }
- [Test]
- public void CalculateTax_IncomeEqualsLowerBoundAndIsLessThenUpperBound_CorrectTax()
- {
- var taxBracket = new TaxBracket(0m, 10m, 50);
- var tax = taxBracket.CalculateTax(2m);
- Assert.AreEqual(tax, 1m);
- }
- [Test]
- public void CalculateTax_IncomeGreaterThenLowerBoundAndEqualsUpperBound_CorrectTax()
- {
- var taxBracket = new TaxBracket(0m, 10m, 50);
- var tax = taxBracket.CalculateTax(10m);
- Assert.AreEqual(tax, 5m);
- }
- [Test]
- public void CalculateTax_IncomeIsLessThenLowerBound_CorrectTax()
- {
- var taxBracket = new TaxBracket(10m, 100m, 100);
- var tax = taxBracket.CalculateTax(5m);
- Assert.AreEqual(tax, 0m);
- }
- }
- #endif
- }
- public interface ITaxBracketSystem : IEnumerable<ITaxBracket>
- {
- decimal CalculateTax(Decimal income);
- void Add(ITaxBracket item);
- }
- public class TaxBracketSystem : List<ITaxBracket>, ITaxBracketSystem
- {
- public decimal CalculateTax(Decimal income)
- {
- if(income < 0)
- throw new ArgumentOutOfRangeException("income", "Income should be non-negative.");
- var tax = this.Sum(r => r.CalculateTax(income));
- return Math.Round(tax,2);
- }
- #if DEBUG
- [TestFixture]
- class TaxBracketSystemTests
- {
- [Test]
- public void Constructor_OneTaxBracket_ConstructedCorrectObject ()
- {
- var taxBracket = new TaxBracket(1m, 2m, 3m);
- var taxSystem = new TaxBracketSystem {taxBracket};
- Assert.AreEqual(taxSystem[0], taxBracket);
- }
- [Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
- public void CalculateTax_NegativeIncome_Throws()
- {
- var taxSystem = new TaxBracketSystem();
- taxSystem.CalculateTax(-100m);
- }
- [Test]
- public void CalculateTax_NoTaxBrackets_ZeroTax ()
- {
- var taxSystem = new TaxBracketSystem();
- var tax = taxSystem.CalculateTax(100m);
- Assert.AreEqual(Decimal.Zero, tax);
- }
- [Test]
- public void CalculateTax_OneTaxBrackets_CorrectTax()
- {
- var taxAmount = 100m;
- var taxBracketMoq = new Mock<ITaxBracket>();
- taxBracketMoq.Setup(taxBracket => taxBracket.CalculateTax(It.IsAny<decimal>())).Returns(taxAmount);
- var taxSystem = new TaxBracketSystem {taxBracketMoq.Object};
- var calculatedTax = taxSystem.CalculateTax(1000m);
- Assert.AreEqual(taxAmount, calculatedTax);
- }
- [Test]
- public void CalculateTax_TwoTaxBrackets_CorrectTax()
- {
- var taxAmount1 = 100m;
- var taxBracketMoq1 = new Mock<ITaxBracket>();
- taxBracketMoq1.Setup(taxBracket => taxBracket.CalculateTax(It.IsAny<decimal>())).Returns(taxAmount1);
- var taxAmount2 = 100m;
- var taxBracketMoq2 = new Mock<ITaxBracket>();
- taxBracketMoq2.Setup(taxBracket => taxBracket.CalculateTax(It.IsAny<decimal>())).Returns(taxAmount2);
- var taxSystem = new TaxBracketSystem { taxBracketMoq1.Object, taxBracketMoq2.Object };
- var tax = taxSystem.CalculateTax(1000m);
- Assert.AreEqual(taxAmount1 + taxAmount2, tax);
- }
- }
- #endif
- }
- #if DEBUG
- [TestFixture]
- class TaxIntegrationTests
- {
- readonly ITaxBracketSystem israeliTaxSystem = new TaxBracketSystem
- {
- new TaxBracket(0, 5070, 10m),
- new TaxBracket(5070, 8660, 14m),
- new TaxBracket(8660, 14070, 23m),
- new TaxBracket(14070, 21240, 30m),
- new TaxBracket(21240, 40230, 33m),
- new TaxBracket(40230, decimal.MaxValue, 45m)
- };
- [Test]
- public void IsraeliTaxSystem_IncomeIs05000_CorrectTax()
- {
- var tax = israeliTaxSystem.CalculateTax(5000);
- Assert.AreEqual(500m, tax);
- }
- [Test]
- public void IsraeliTaxSystem_IncomeIs05800_CorrectTax()
- {
- var tax = israeliTaxSystem.CalculateTax(5800);
- Assert.AreEqual(609.2m, tax);
- }
- [Test]
- public void IsraeliTaxSystem_IncomeIs09000_CorrectTax()
- {
- var tax = israeliTaxSystem.CalculateTax(9000);
- Assert.AreEqual(1087.8m, tax);
- }
- [Test]
- public void IsraeliTaxSystem_IncomeIs15000_CorrectTax()
- {
- var tax = israeliTaxSystem.CalculateTax(15000);
- Assert.AreEqual(2532.9, tax);
- }
- [Test]
- public void IsraeliTaxSystem_IncomeIs50000_CorrectTax()
- {
- var tax = israeliTaxSystem.CalculateTax(50000);
- Assert.AreEqual(15068.1m, tax);
- }
- }
- #endif
- }
Advertisement
Add Comment
Please, Sign In to add comment