Reputation: 65
I am currently trying to test a method using Mockito and I am stuck on a certain method.
For example, there are classes called Car and CarSystem.
The car class contains two parameters, Name(String) and its License Plate(String) and their getter/setter methods.
The method I am trying to test using Mockito is a method called, addCar which is in the CarSystem class.
CarSystem class:
private final List<Car> cars= new ArrayList<>();
public Car addCar(String name, String plateNumber) throws IllegalStateException {
Car clash = getCar(plateNumber);
if (null != clash) throw new IllegalStateException("Car with that Number already exists");
Car car = new Car(name, plateNumber);
cars.add(car);
return car;
}
public Car getCar(String match) {
for (Car car: cars) {
if (car.getPlateNumber().equals(match)) return car;
}
return null;
}
What I am trying to test is the two things:
It successfully throws an IllegalStateException exception when there is a car with the plate number that already exists in the car list.
It successfully adds a car to the list.
What I did solely using JUnit is:
@Test
public void testAddCar_ThrowingException() {
try {
CarSystem sys = new CarSystem();
Car car = sys.addCar("1234", "Toyota123");
Car car1= sys.addCar("1234", "Honda123");
Assert.fail();
} catch(IllegalStateException e) {
System.out.println(e);
}
}
@Test
public void testAddCar() {
CarSystem sys = new CarSystem();
Car car = sys.addCar("1234", "Toyota123");
Assert.assertEquals(sys.getCar(1234).getName(), "Toyota123");
}
But I have no idea how to test them using Mockito... Can anyone please help me or give me a hint about this?
P.S) I can freely change the content of the classes for Mockito test.
Upvotes: 0
Views: 114
Reputation: 14999
I would not create the Car
to be added inside the method but have it passed in as a parameter, ie
interface CarService {
Car addCar(Car toAdd);
Car getCar(String plateNumber);
}
Since you are testing the service itself, you cannot mock it - only the car. Since the Car
's only data you access is getPlateNumber
, a test would look something like this:
class ScratchTest {
private CarService sut;
@Before
public void before() {
sut = new CarService();
}
@Test
public void addSucceeds() {
String plateNumber = "new";
Car toAdd = mock(Car.class);
when(toAdd.getPlateNumber()).thenReturn(plateNumber);
Car added = sut.addCar(toAdd);
// assert return value
assertSame(toAdd, added);
// assert car now available via get
Car stored = sut.getCar(plateNumber);
assertSame(toAdd, stored);
}
@Test(expected = IllegalArgumentException.class)
public void addFails() {
Car existing = mock(Car.class);
String plateNumber = "existing";
when(existing.getPlateNumber()).thenReturn(plateNumber);
sut.addCar(existing);
Car toAdd = mock(Car.class);
when(toAdd.getPlateNumber()).thenReturn(plateNumber);
sut.addCar(toAdd);
}
}
You cannot really test add and get independently, because they are invariants of each other: 1. If add
is called with a car with a new plate number, a subsequent get
given that plate number will retrieve it, and 2. If get
is called with the plate number of a Car
for which add
has been called before, it will be returned.
Upvotes: 1