How to test a switch case method with JUnit and Mockito - java

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);
// }

#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);
}

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.

Related

How to use a switch case in test cases without passing values to switch() method [duplicate]

I've looked at various Q&As on SO similar to this question but haven't found a solution.
What I have is an enum which represents different ways to view a TV Guide...
In the NDroid Application class
static enum guideView {
GUIDE_VIEW_SEVEN_DAY,
GUIDE_VIEW_NOW_SHOWING,
GUIDE_VIEW_ALL_TIMESLOTS
}
...when the user changes the view an event handler receives an int from 0-2 and I'd like to do something like this...
In an Android Activity onClick(DialogInterface dialog, int which) event handler
// 'which' is an int from 0-2
switch (which) {
case NDroid.guideView.GUIDE_VIEW_SEVEN_DAY:
...
break;
}
I'm used to C# enums and select/case statements which would allow something like the above and I know Java does things differently but I just can't make sense of what I need to do.
Am I going to have to resort to if statements? There will likely only ever be 3 choices so I could do it but I wondered how it could be done with switch-case in Java.
EDIT Sorry I didn't completely expand on the issue as I was looking at it as being a generic Java issue. I've added to the question to explain a bit further.
There isn't anything that's Android specific which is why I didn't tag it as Android but the enum is defined in the Application class and the code where I wan't the switch is in an Activity. The enum is static as I need to access it from multiple Activities.
The part you're missing is converting from the integer to the type-safe enum. Java will not do it automatically. There's a couple of ways you can go about this:
Use a list of static final ints rather than a type-safe enum and switch on the int value you receive (this is the pre-Java 5 approach)
Switch on either a specified id value (as described by heneryville) or the ordinal value of the enum values; i.e. guideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
Determine the enum value represented by the int value and then switch on the enum value.
enum GuideView {
SEVEN_DAY,
NOW_SHOWING,
ALL_TIMESLOTS
}
// Working on the assumption that your int value is
// the ordinal value of the items in your enum
public void onClick(DialogInterface dialog, int which) {
// do your own bounds checking
GuideView whichView = GuideView.values()[which];
switch (whichView) {
case SEVEN_DAY:
...
break;
case NOW_SHOWING:
...
break;
}
}
You may find it more helpful / less error prone to write a custom valueOf implementation that takes your integer values as an argument to resolve the appropriate enum value and lets you centralize your bounds checking.
If whichView is an object of the GuideView Enum, following works well. Please note that there is no qualifier for the constant after case.
switch (whichView) {
case SEVEN_DAY:
...
break;
case NOW_SHOWING:
...
break;
}
The enums should not be qualified within the case label like what you have NDroid.guideView.GUIDE_VIEW_SEVEN_DAY, instead you should remove the qualification and use GUIDE_VIEW_SEVEN_DAY
I like a few usages of Java enum:
.name() allows you to fetch the enum name in String.
.ordinal() allow you to get the integer value, 0-based.
You can attach other value parameters with each enum.
and, of course, switch enabled.
enum with value parameters:
enum StateEnum {
UNDEFINED_POLL ( 1 * 1000L, 4 * 1000L),
SUPPORT_POLL ( 1 * 1000L, 5 * 1000L),
FAST_POLL ( 2 * 1000L, 4 * 60 * 1000L),
NO_POLL ( 1 * 1000L, 6 * 1000L);
...
}
switch example:
private void queuePoll(StateEnum se) {
// debug print se.name() if needed
switch (se) {
case UNDEFINED_POLL:
...
break;
case SUPPORT_POLL:
...
break;
This should work in the way that you describe. What error are you getting? If you could pastebin your code that would help.
http://download.oracle.com/javase/tutorial/java/javaOO/enum.html
EDIT: Are you sure you want to define a static enum? That doesn't sound right to me. An enum is much like any other object. If your code compiles and runs but gives incorrect results, this would probably be why.
Short associative function example:
public String getIcon(TipoNotificacao tipo)
{
switch (tipo){
case Comentou : return "fa fa-comments";
case ConviteEnviou : return "icon-envelope";
case ConviteAceitou : return "fa fa-bolt";
default: return "";
}
}
Like #Dhanushka said, omit the qualifier inside "switch" is the key.
enumerations accessing is very simple in switch case
private TYPE currentView;
//declaration of enum
public enum TYPE {
FIRST, SECOND, THIRD
};
//handling in switch case
switch (getCurrentView())
{
case FIRST:
break;
case SECOND:
break;
case THIRD:
break;
}
//getter and setter of the enum
public void setCurrentView(TYPE currentView) {
this.currentView = currentView;
}
public TYPE getCurrentView() {
return currentView;
}
//usage of setting the enum
setCurrentView(TYPE.FIRST);
avoid the accessing of TYPE.FIRST.ordinal() it is not recommended always
I am doing it like
public enum State
{
// Retrieving, // the MediaRetriever is retrieving music //
Stopped, // media player is stopped and not prepared to play
Preparing, // media player is preparing...
Playing, // playback active (media player ready!). (but the media player
// may actually be
// paused in this state if we don't have audio focus. But we
// stay in this state
// so that we know we have to resume playback once we get
// focus back)
Paused; // playback paused (media player ready!)
//public final static State[] vals = State.values();//copy the values(), calling values() clones the array
};
public State getState()
{
return mState;
}
And use in Switch Statement
switch (mService.getState())
{
case Stopped:
case Paused:
playPause.setBackgroundResource(R.drawable.selplay);
break;
case Preparing:
case Playing:
playPause.setBackgroundResource(R.drawable.selpause);
break;
}

Test if object was properly created

I'm putting more attention into unit tests these days and I got in a situation for which I'm not sure how to make a good test.
I have a function which creates and returns an object of class X. This X class is part of the framework, so I'm not very familiar with it's implementation and I don't have freedom as in the case of my "regular collaborator classes" (the ones which I have written). Also, when I pass some arguments I cannot check if object X is set to right parameters and I'm not able to pass mock in some cases.
My question is - how to check if this object was properly created, that is, to check which parameters were passed to its constructor? And how to avoid problem when constructor throws an exception when I pass a mock?
Maybe I'm not clear enough, here is a snippet:
public class InputSplitCreator {
Table table;
Scan scan;
RegionLocator regionLocator;
public InputSplitCreator(Table table, Scan scan, RegionLocator regionLocator) {
this.table = table;
this.scan = scan;
this.regionLocator = regionLocator;
}
public InputSplit getInputSplit(String scanStart, String scanStop, Pair<byte[][], byte[][]> startEndKeys, int i) {
String start = Bytes.toString(startEndKeys.getFirst()[i]);
String end = Bytes.toString(startEndKeys.getSecond()[i]);
String startSalt;
if (start.length() == 0)
startSalt = "0";
else
startSalt = start.substring(0, 1);
byte[] startRowKey = Bytes.toBytes(startSalt + "-" + scanStart);
byte[] endRowKey = Bytes.toBytes(startSalt + "-" + scanStop);
TableSplit tableSplit;
try {
HRegionLocation regionLocation = regionLocator.getRegionLocation(startEndKeys.getFirst()[i]);
String hostnamePort = regionLocation.getHostnamePort();
tableSplit = new TableSplit(table.getName(), scan, startRowKey, endRowKey, hostnamePort);
} catch (IOException ex) {
throw new HBaseRetrievalException("Problem while trying to find region location for region " + i, ex);
}
return tableSplit;
}
}
So, this creates an InputSplit. I would like to know whether this split is created with correct parameters. How to do that?
If the class is part of a framework, then you shouldn't test it directly, as the framework has tested it for you. If you still want to test the behaviour of this object, look at the cause-reaction this object would cause. More specifically: mock the object, have it do stuff and check if the affected objects (which you can control) carry out the expected behaviour or are in the correct state.
For more details you should probably update your answer with the framework you're using and the class of said framework you wish to test
This is possibly one of those cases where you shouldn't be testing it directly. This object is supposedly USED for something, yes? If it's not created correctly, some part of your code will break, no?
At some point or another, your application depends on this created object to behave in a certain way, so you can test it implicitly by testing that these procedures that depend on it are working correctly.
This can save you from coupling more abstract use cases from the internal workings and types of the framework.

Is it possible to replace if-else with switch statement using strings as switching values?

I'm wondering if it's possible to use switch statement instead of if-else one in this case. Variables are taken from JComboBoxes and processed by ActionEvent here:
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == comboUnit) {
String unit = comboUnit.getSelectedItem().toString();
if (unit.equals("Unit 1")) {
unitValue = Double.parseDouble(tfUnit.getText());
valMeter = unitValue * defined1;
labelDesc.setText("Unit 1");
convert();
}
else if (unit.equals("Unit 2")) {
unitValue = Double.parseDouble(tfUnit.getText());
valMeter = unitValue * defined2;
labelDesc.setText("Unit 2");
convert();
}
(...)
I was trying to pass pure strings as the values but with no success. Do you have any hints on how it should be done (and if it's even possible)?
Java 7 allows you to switch on Strings.
Your code needs refactoring though, and the question of whether to use switch or enumerations or maps, is something that comes second, I would say.
You have too much duplicated code doing essentially the same thing. I am referring to:
unitValue = Double.parseDouble(tfUnit.getText());
valMeter = unitValue * defined1;
labelDesc.setText("Unit 1");
convert();
Obviously, because you multiply using different factors depending on the unit used, you need a function of unit evaluating to the factor to use. In less mathematical terms, you need something that yields value of either defined1 or defined2 depending on a string supplied. You already have the unit referring to the "name" of your unit in question, you can use it. I call the method returning the factor for factor, taking in a unit name and returning a Number (since it does not follow from your example whether you are multiplying integers or real numbers of some sort). I am also assuming your defined1 and defined2 etc, are variables or literals.
unitValue = Double.parseDouble(tfUnit.getText());
valMeter = unitValue * factor(unit);
labelDesc.setText(unit);
convert();
Number factor(String unitName) {
switch(unitName) {
case "Unit 1": return defined1;
case "Unit 2": return defined2;
default: throw new Exception("Unknown unit");
}
}
The method itself is where your "to switch or not to switch" problem creeps in. You are free to use a map if you want:
Map<String, Number> unitNameValueMap = new HashMap<String, Number>();
unitNameValueMap.put("Unit 1", defined1);
unitNameValueMap.put("Unit 2", defined2);
Number factor(String unitName) {
Number result = unitNameValueMap.get(unitName);
if(result == null) throw new Exception("Unknown unit");
return result;
}
Or you can use enumerations:
enum UnitValue {
UNIT1(defined1), UNIT2(defined2);
final Number value;
private UnitValue(Number value) {
this.value = value;
}
}
Number factor(String unitName) {
return Enum.valueOf(UnitValue.class, "UNIT" + Integer.parseInt(unitName.substring(5)).value;
}
You can even switch or use a map inside enumerations, which will give you good code readability as well.
You need to profile your program to see if you need switch-based solution or enum-based one or a map-based one. The way it currently stands and as you can see for yourself, the enum-based solution is a bit messy because of relationship between your unit names, enumeration constants, and their values. If someone can do better with enums, then take their code instead, naturally.
Usually, shortest code is best, as it is easier to read and most often understand. But be careful with maps - they induce more overhead than other solutions, so I for one prefer to use them where I have fewer maps with many keys each, not the other way around.
You mean like
switch (unit) {
case "Unit 1":
// do something
break;
case "Unit 2":
}
?
Yes you can, starting with Java7.
But in your case, you don't seem to need neither switch nor if/else. You do the same thing in both cases :
String unit = comboUnit.getSelectedItem().toString();
unitValue = Double.parseDouble(tfUnit.getText());
valMeter = unitValue * defined1;
labelDesc.setText(unit);
convert();
You can use Enum and replace string with Enum values
public static void main(String[] args) {
Units unit = Units.Unit1;
switch (unit) {
case Unit1:
break;
case Unit2:
break;
}
}
enum Units {
Unit1, Unit2,
}
Java 7 allows you Using Strings in switch Statements
Only in Java 7 and later is it possible to use Strings in a switch-case statement. Here is a link to the documentation, you will need to scroll down to the String section.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html

Verifying partially ordered method invocations in JMockit

I'm trying to write a unit test (using JMockit) that verifies that methods are called according to a partial order. The specific use case is ensuring that certain operations are called inside a transaction, but more generally I want to verify something like this:
Method beginTransaction is called.
Methods operation1 through to operationN are called in any order.
Method endTransaction is called.
Method someOtherOperation is called some time before, during or after the transaction.
The Expectations and Verifications APIs don't seem to be able to handle this requirement.
If I have a #Mocked BusinessObject bo I can verify that the right methods are called (in any order) with this:
new Verifications() {{
bo.beginTransaction();
bo.endTransaction();
bo.operation1();
bo.operation2();
bo.someOtherOperation();
}};
optionally making it a FullVerifications to check that there are no other side-effects.
To check the ordering constraints I can do something like this:
new VerificationsInOrder() {{
bo.beginTransaction();
unverifiedInvocations();
bo.endTransaction();
}};
but this does not handle the someOtherOperation case. I can't replace the unverifiedInvocations with bo.operation1(); bo.operation2() because that puts a total ordering on the invocations. A correct implementation of the business method could call bo.operation2(); bo.operation1().
If I make it:
new VerificationsInOrder() {{
unverifiedInvocations();
bo.beginTransaction();
unverifiedInvocations();
bo.endTransaction();
unverifiedInvocations();
}};
then I get a "No unverified invocations left" failure when someOtherOperation is called before the transaction. Trying bo.someOtherOperation(); minTimes = 0 also doesn't work.
So: Is there a clean way to specify partial ordering requirements on method calls using the Expectations/Verifications API in JMockIt? Or do I have to use a MockClass and manually keep track of invocations, a la:
#MockClass(realClass = BusinessObject.class)
public class MockBO {
private boolean op1Called = false;
private boolean op2Called = false;
private boolean beginCalled = false;
#Mock(invocations = 1)
public void operation1() {
op1Called = true;
}
#Mock(invocations = 1)
public void operation2() {
op2Called = true;
}
#Mock(invocations = 1)
public void someOtherOperation() {}
#Mock(invocations = 1)
public void beginTransaction() {
assertFalse(op1Called);
assertFalse(op2Called);
beginCalled = true;
}
#Mock(invocations = 1)
public void endTransaction() {
assertTrue(beginCalled);
assertTrue(op1Called);
assertTrue(op2Called);
}
}
if you really need such test then: don't use mocking library but create your own mock with state inside that can simply check the correct order of methods.
but testing order of invocations is usually a bad sign. my advice would be: don't test it, refactor. you should test your logic and results rather than a sequence of invocations. check if side effects are correct (database content, services interaction etc). if you test the sequence then your test is basically exact copy of your production code. so what's the added value of such test? and such test is also very fragile (as any duplication).
maybe you should make your code looks like that:
beginTransaction()
doTransactionalStuff()
endTransaction()
doNonTransactionalStuff()
From my usage of jmockit, I believe the answer is no even in the latest version 1.49.
You can implement this type of advanced verification using a MockUp extension with some internal fields to keep track of which functions get called, when, and in what order.
For example, I implemented a simple MockUp to track method call counts. The purpose of this example is real, for where the Verifications and Expectations times fields did not work when mocking a ThreadGroup (useful for other sensitive types as well):
public class CalledCheckMockUp<T> extends MockUp<T>
{
private Map<String, Boolean> calledMap = Maps.newHashMap();
private Map<String, AtomicInteger> calledCountMap = Maps.newHashMap();
public void markAsCalled(String methodCalled)
{
if (methodCalled == null)
{
Log.logWarning("Caller attempted to mark a method string" +
" that is null as called, this is surely" +
" either a logic error or an unhandled edge" +
" case.");
}
else
{
calledMap.put(methodCalled, Boolean.TRUE);
calledCountMap.putIfAbsent(methodCalled, new AtomicInteger()).
incrementAndGet();
}
}
public int methodCallCount(String method)
{
return calledCountMap.putIfAbsent(method, new AtomicInteger()).get();
}
public boolean wasMethodCalled(String method)
{
if (method == null)
{
Log.logWarning("Caller attempted to mark a method string" +
" that is null as called, this is surely" +
" either a logic error or an unhandled edge" +
" case.");
return false;
}
return calledMap.containsKey(method) ? calledMap.get(method) :
Boolean.FALSE;
}
}
With usage like the following, where cut1 is a dynamic proxy type that wraps an actual ThreadGroup:
String methodId = "activeCount";
CalledCheckMockUp<ThreadGroup> calledChecker = new CalledCheckMockUp<ThreadGroup>()
{
#Mock
public int activeCount()
{
markAsCalled(methodId);
return active;
}
};
. . .
int callCount = 0;
int activeCount = cut1.activeCount();
callCount += 1;
Assertions.assertTrue(calledChecker.wasMethodCalled(methodId));
Assertions.assertEquals(callCount, calledChecker.methodCallCount(methodId));
I know question is old and this example doesn't fit OP's use case exactly, but hoping it may help guide others to a potential solution that come looking (or the OP, god-forbid this is still unsolved for an important use case, which is unlikely).
Given the complexity of what OP is trying to do, it may help to override the $advice method in your custom MockUp to ease differentiating and recording method calls. Docs here: Applying AOP-style advice.

Duplicate Check in Java

I am writing a small integration piece to to retrive the testcases from TestCase Management tool in java, in which i have the following scenarios:-
1) I have testcase which is “failed”, that time I am checking whether there is any defect which is already exists in the Defect management tool for the failed testcase using the testcase name , because the testcase name and the defect name are same in our case.
If not I am logging the new defect. This is fine.
2) In another case, I have testcase which is “Passed” at the first time, for that also I am checking the whether there are any duplicate defect is present in the Defect management tool , eventhough I am not going to log any defect.
This I am doing because, I don’t know whether the testcase is “Pass” or “Fail” in the first attempt or not. Hence I am doing this mandatory check , to see whether the duplicate defect exists or not for both “pass” and “fail” testcase.
I know that it is wrong to check the duplicate existence of the defect for the “pass” testcase. But there is no option I have. Is there any way we can ignore calling duplicate existence of the defect method if the testcase is “passed”?
I want your guys opinion on this.
This is the code which i have:-
private int NOT_TESTED = 0;
private int PASSED_1 = 0;
private int PASSED_2 = 0;
private int FAILED =0;
private String testStatus = "pass"; // will be fetched dynamically
private void execute(){
if(testStatus.equalsIgnoreCase("fail")){
//FAILED--;
FAILED = FAILED + 1;
System.out.println("the failed value is:"+FAILED);
}else if(testStatus.equalsIgnoreCase("pass")){// first attempt
PASSED_1 = PASSED_1 + 1;
System.out.println("the Passed_1 value is:"+PASSED_1);
if(PASSED_1 == 1){
System.out.println("Passed in the first attempt, hence no need to create a defect");
}
}else if(testStatus.equalsIgnoreCase("pass") && FAILED ==1){// second attempt
PASSED_2 = PASSED_2+1;
System.out.println("the Passed_2 value is:"+PASSED_2);
if(PASSED_2 ==1){
System.out.println("Passed in the second attempt, create a defect");
// logic to create a new defect
}
}else {
System.out.println("The test not tested");
}
}
This code is not working as it always go to the first pass attempt state, hence please do provide a solution to find if the testcase is passed in the second attempt (FAIL->PASS) so that we can take appropriate action on this.
Thanks in advance.
if the condition (testStatus.equalsIgnoreCase("pass") && FAILED ==1) is true, it means that the condition before it is also true:
if(testStatus.equalsIgnoreCase("pass"))
Since you used if-else, it will go into the first condition and then skip the rest.
Switching between those two will give you the desired result I think.

Categories