I have a similar scenario to this:
public class VatCalculator { public decimal GetValueWithVat(decimal value, decimal? vatRatePercentage) { if(vatRate == null) { return value; } return value * (1 + (vatRate / 100)); } } public ReceiptGenerator { private readonly VatCalculator _vatCalculator; public ReceiptGenerator(VatCalculator vatCalculator) { _vatCalculator = vatCalculator; } public Receipt GenerateReceipt(Item purchasedItem, decimal? vatRate) { var receipt = new Receipt(); receipt.PriceBeforeVat = purchasedItem.Price receipt.PriceAfterVat = _vatCalculator.GetValueWithVat(purchasedItem.Price, vatRate) } } In this case, I have a few unit tests I'd like to write, e.g.
- If no VAT rate is provided, the 'Price After Vat' value should be equal to the purchased item's price.
- If a VAT rate is provided, the 'Price After Vat' value should be adjusted accordingly
My question is whether I should write these unit tests at the level of the ReceiptGenerator class or the VatCalculator class.
If I test at the ReceiptGenerator class level it means I have more durable tests; The code of GenerateReceipt can be refactored e.g. to use a private method or an API and the tests should still pass with no changes. But this seems like too large of a scope for a unit test, my understanding was that it should be a very granulargranular focused test
If I test at the VatCalculator level I can use that class in other consumers (for example, if I move my business online, I can use it to provide on-the-go prices for customers browsing a product) without having to test the consumers themselves.