Reputation: 155
I have the following methods
//my method
public Car polishCar(Car car){
car.setPolish(true);
car.setPolishDate(new Date());
return car;
}
//myMethod
public Car washCar(Car car){
car.setWash(true);
car.setWashDate(new Date());
return car;
}
// mainMethod
public Car serviceCar(){
Car car = new Car();
myMethod.polishCar(car);
myMethod.washCar(car);
......
return Car;
}
This is what I have code for my unit test with mockito, I need to create 2 different Car objects which look redundant and keep adding new value to it.
Car pCar = new Car();
pCar.setPolish(true);
pCar.setPolishDate(new Date());
//first call
when(myMethod.polishCar(any(Car.class))).thenReturn(pCar);
Car wCar = new Car();
wCar.setPolish(true);
wCar.setPolishDate(new Date());
wCar.setWash(true);
wCar.setWashDate(new Date());
//second call with same car object from previous, and return same car object with additional value
when(myMethod.washCar(eq(pCar))).thenReturn(wCar);
Car testCar = mainMethod.serviceCar();
// check if they are same instance
assertEquals(testCar, wCar);
assertEquals("true", wCar.getWash());
assertEquals("true", wCar.polish());
How can I better handle this scenario to make mockito return the same & updated object (same instance) and keep passing to the next method call?
So the main point is I want to have 1 car object and this car object will pass to number of method to update this car object.
// Create 1 car object
Car singleCar = new Car();
//pass to first method, and return singleCar with updated polish & polishDate
when(myMethod.polishCar(eq(singleCar))).thenReturn(singleCar);
//pass to second method, and return singleCar with updated wash and washDate
when(myMethod.washCar(eq(singleCar))).thenReturn(singleCar);
// call main method for testing
Car testCar = mainMethod.serviceCar();
// assert testCar == singleCar
// assert singleCar is updated (wash == true & polish == true)
Is there any way to reuse the same object here ?
Thank you.
Upvotes: 0
Views: 442
Reputation: 106
You can use an ArgumentCaptor to capture the argument (your mock instance pCar). Then use that value in your test. Below is pseudo code but essentially how argument captor works:
@Mock
Car pcar;
@Captor
ArgumentCaptor<Car> carCaptor;
when(myMethod.polishCar(
any(Car.class))).thenReturn(pCar);
Mockito.verify(car)
.polishCar(carCaptor.capture());
The captured argument would be the pCar which you can then use through out the test
Upvotes: 0
Reputation: 90427
There is no sense to use mock in this case. Just create a real SUT and the real car. Simply call the test method for the real car instance and directly verify the car 's state.
@Test
public polishAndCarTest(){
Car car = new Car();
Date now = new Date();
sut.polishCar(car);
sut.washCar(car);
assertThat(car.isPolish()).isTrue();
assertThat(car.getPolishDate()).isCloseTo(now,2);
assertThat(car.isWash()).isTrue();
assertThat(car.getWashDate()).isCloseTo(now,2);
}
Notes :
It is better that you can refactor polishCar()
and washCar()
such that it can accept a given date as the input argument rather than hardcode it as the current time . After that , you can pass a testing date when calling these methods in the test case and can easily verify the polish date and wash date is really updated to this date.
If you don't like this , you can use assertj to verify these date is close to within 2 millisecond after the moment when polishCar()
/ washCar()
is called which is fine enough to me.
Upvotes: 1
Reputation: 538
Use any
Matcher like any(ParamClass.class)
.
In your case when(myMethod.washCar(any(Car.class))).thenReturn(wCar);
Upvotes: 0