Reputation: 95
Consider this class:
public class Customer {
private final List<Rental> rentals;
public Customer() {
this.rentals = new ArrayList<>();
}
public void addRental(Rental rental) {
if (rental != null) {
this.rentals.add(rental);
}
}
public BigDecimal sumRentals() {
return rentals.stream()
.map(r -> r.getPrice())
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
I want to create a unit test on the addRental()
method, yet I don't want to publish a getter to the rental
member, nor do I plan on publishing a consists()
method and writing it just for the sake of tests seems a bad practise.
So the question is: how do I go about testing addRental()
? Do I make use of the sumRentals()
method, even if the test is indirect (I would be checking if the sum of elements changed correctly and not if the element was actually added to the collection)? Do I forget about testing addRental()
altogether since it's so trivial? What if it wasn't though and there was some more logic to it?
Upvotes: 1
Views: 248
Reputation: 26502
I would go for a guard test or with a delta test:
Guard Test:
// arrange
Customer customer = new Customer();
assertThat(customer.sumRentals() == BigDecimal.ZERO);
// act
customer.addRental(new Rental());
// assert
assertThat(customer.sumRentals() == BigDecial.valueOf(1));
Delta Test:
// arrange
Customer customer = new Customer();
initialSum = customer.sumRentals();
// act
customer.addRental(new Rental());
// assert
assertThat(customer.sumRentals() == initialSum + 1);
Or both.. using the available api all the time. The same as with testing the workings of a list.. you test the add
, but you check with the size
.
Upvotes: 0
Reputation: 50716
Unit testing should generally test the behavior of your classes, not the implementation. If the only visible effect of addRental()
is via sumRentals()
, that's the right method to test against.
Say tomorrow you decide to modify your implementation:
public class Customer {
private BigDecimal rentalSum = BigDecimal.ZERO;
public void addRental(Rental rental) {
rentalSum = rentalSum.add(rental.getPrice());
}
public BigDecimal sumRentals() {
return rentalSum;
}
}
Your unit test shouldn't have to know that the implementation changed. If you test against sumRentals()
, it won't.
Upvotes: 2