Ok so, I need to test this method which contains a switch case statement:
@Override
public int delete() {
LOGGER.info("--------------------------------------------------------------------------------------------------\n"
"Please select whether you would like to delete the entire order, or an item from the order");
LOGGER.info("DEL ORDER/DEL ITEM");
String action = utils.getString();
action = action.toUpperCase();
switch (action) {
case "DEL ORDER":
LOGGER.info("--------------------------------------------------------------------------------------------------\n"
"Please enter the order id of the order you would like to delete:");
Long order_id = utils.getLong();
orderDAO.delete(order_id);
LOGGER.info("------------------------------Order has successfully been deleted!------------------------------");
break;
case "DEL ITEM":
LOGGER.info("--------------------------------------------------------------------------------------------------\n"
"Please enter the order id you would like to delete an item from:");
Long order_id2 = utils.getLong();
LOGGER.info("Please enter the item id you would like to delete from the order:");
Long item_id = utils.getLong();
orderDAO.itemDelete(order_id2, item_id);
LOGGER.info("------------------------------Item from order has successfully been deleted!------------------------------");
break;
default:
LOGGER.info("Invalid input, please try again!");
return 0;
}
return 0;
}
but what I've got so far isn't giving me any coverage at all! Not sure where I'm going wrong but it's all in red... I assumed I could split it into two testing methods as they are separate "branches" of the switch statement, so I'm not sure why this isn't working. I know the code itself works as I have tested it with SQL entries.
@Test
public void testDeleteOrder() {
long order_id = 1L;
String action = "DEL ORDER";
Mockito.when(this.utils.getString()).thenReturn(action);
Mockito.when(utils.getLong()).thenReturn(order_id);
Mockito.when(dao.delete(order_id)).thenReturn(1);
// assertEquals(1, this.controller.delete());
//
// Mockito.verify(utils, Mockito.times(1)).getLong();
// Mockito.verify(dao, Mockito.times(1)).delete(order_id);
}
//
// public void testDeleteItem() {
// long order_id2 = 1L;
// long item_id = 1L;
// String action = "DEL ITEM";
// Mockito.when(this.utils.getString()).thenReturn(action);
// Mockito.when(utils.getLong()).thenReturn(order_id2);
// Mockito.when(utils.getLong()).thenReturn(item_id);
// Mockito.when(dao.itemDelete(order_id2, item_id)).thenReturn(1);
////
//// assertEquals(1, this.controller.delete());
////
//// Mockito.verify(utils, Mockito.times(2)).getLong();
//// Mockito.verify(dao, Mockito.times(1)).itemDelete(order_id2, item_id);
// }
CodePudding user response:
@ParameterizedTest
@ValueSource(strings = {"DEL ORDER", "DEL ITEM"})
void testMethod(String action) {
Mockito.when(this.utils.getString()).thenReturn(action);
Mockito.when(utils.getLong()).thenReturn(order_id);
Mockito.when(dao.delete(order_id)).thenReturn(1);
switch (action) {
case "DEL ORDER":
verify(dao).delete(anyLong());
break;
case "DEL ITEM":
verify(dao).itemDelete(anyLong(), anyLong());
break;
default:
verifyNoInteractions(dao);
}
verifyNoMoreInteractions(dao);
}
CodePudding user response:
Testing a method and the actual coverage are the targets defined while implementing it. Following the TDD principles on the best scenarios, tests are created on the same time as the method is being implemented, so that you can pick easily design/dependency problems and avoid them. In that way the method would be constantly refactored so that the code remains simple and it can be properly tested and write a test class. Going the opposite way on large services / big flows, usually is not easy, as you would end up mocking every single dependency/entity required and miss the actual test purpose.
This means that you would define your actual test coverage, based on the scope and the areas you consider as most harmful.
Sharing some ideas.
Imagine that you have to write a test for the below method :
public int sum(int a, int b) {
return a b;
}
Things are very simple here, no dependencies(dao,services) and we know what we expect. The only question that rises, is whether we would need numeric validation etc, but thats again on the actual scope.
So our test would be something like (simpler code, simpler the test) :
assertEquals(5, aBean.sum(2,3));
Getting on your sample again sharing an idea on how you can break it up, based on the implementation by looking on the most important areas:
- DAO wiring
Testing against the actual dependency injection, to confirm that bean creation is successful. Of course this is a container matter, so you would need to check this in very specific occasions.
- Switch case
Verifying that the switch case is working of course is not required, but verifying that the expected methods are executed in each action is a good point.
- DB operation
This is more extreme as it requires external integration either with a mock or a development DataBase. We need to verify that the method does what it says, so we actually need to verify that the sample.entry has been indeed removed from the database. The last point might be your full coverage, as it would cover both that the actions are getting executed and that the expected result is confirmed.
I would also suggest to take a look on TDD practices and some samples with Junit Mockito to check the usages of Mockito.when, Mockito.verify, Spies.