I need to know how to test the default case in a switch statement with junit. I can't change the code itself and I'm trying for 100% coverage but I don't know how to test my default. Helps?
public Hello helloSwitch() {
Hello hi = Hello.A;
switch (this) {
case A:
hi = Hello.B;
break;
case B:
hi = Hello.C;
break;
case C:
hi = Hello.A;
break;
default:
hi = Hello.A;
break;
}
I had to modify the code a fair bit so sorry that it looks silly. I just need to know how to write a junit to test the default, I've tested everything else.
I can't change this code.
Edit: changed
Edit: This code isn't important I jut need to know how to write the unit test for the default
Edit: I can't change, the code itself, I'm only writing the tests. I need 100% coverage though.
Let me assume that 'hallo' is a variable set somewhere outside the given method. Let me further assume that the Enum type currently only allows values present in the switch statement.
In this case you can use "null" to trigger the default case. In this case the default statement is unreachable and should not be there at all. While there might be ways to still "test" this - meaning to execute the code running a test - this would not add any benefit.
If you have more enum constants available than pick any covered by the default case.
As some already have mentioned:
dead code cannot and should not be tested but removed.
100% test coverage sounds nice but usually is not a realistic or sensible goal
in my opinion test shouldn't even know about the code in a method but test the method as a black box.
If you are using JaCoCo then maybe vote for this improvement to ignore default cases which can't be covered: https://github.com/jacoco/jacoco/issues/1211
visit this link can help you :
[JUnit is a standardized framework for testing Java units (that is, Java classes). JUnit can be automated to take the some of the work out of testing.
Imagine you’ve created an enum type with three values: GREEN, YELLOW, and RED. Listing 1 contains the code:
http://www.dummies.com/programming/java/using-junit ]1
Related
I'm trying to create Unit tests for a project. In my project I have a Menu Class, and a VerticalOptions Class.
My menu class has a private VerticalOptions object and a public handleInput method.
When I call my menu's handleInput(key) method, depending on the key I give it it'll do different things, namely call different methods of my VerticalOptions object.
I want to make a unitTest to see if the methods being called are the correct ones, how can I do that?
I've tried adding a Mockito spy to my menu, however since I want to test if the method being called was the method in the private VerticalOptions object, it doesn't really work.
I've also tried putting the spy on the VerticalOptions object, after getting it with a getVerticalOptions method, but it also doesn't work.
public void handleInput(InputKey key)
{
switch (key) {
case S:
case DOWN:
optionsInterface.cycleDown();
break;
case W:
case UP:
optionsInterface.cycleUp();
break;
case SPACE:
case ENTER:
optionsInterface.select();
break;
default:
break;
}
}
#Test
public void testInput() {
MainMenu menu = new MainMenu(game);
VerticalButtonInterface buttonInterface = menu.getOptionsInterface();
VerticalButtonInterface spy = spy(buttonInterface);
menu.handleInput(InputKey.DOWN);
verify(spy, times(1)).cycleDown();
}
This is the test failure I got:
Wanted but not invoked:
verticalButtonInterface.cycleDown();
-> at MenuTest.testInput(MenuTest.java:60)
Actually, there were zero interactions with this mock.
I will give you an alternative view on this. I have seen a lot of people going down the wrong path and when you do that, everything else becomes hard to do / test, which is exactly what you are doing now.
Start here, what are you trying to achieve?
I want to test and make sure that a certain method is called ...
Is this a good thing? What is a unit test not meant to have? That is deep knowledge of the code.
Why? Because every time you make slight changes to the code, you'll have to change the test because of this deep knowledge. if you have 1000 tests, you're in for a hard road.
Ok, so we now know what the problem is, so how do we solve it? Well, first let's make sure we can have a test without deep knowledge of the code.
How do we do that? Well, imagine that your code adds an extra step, a flag which sets a state. You might have a flag which stores a resulting state ...
you have 3 methods you want to call, so you will need 3 different states, so create a variable which reflects that, be it a string, or an enum or whatever else makes you happy.
For example sake, let's say we create a string with 3 possible values: cycleDown, cycleUp and select.
your code starts to look something like :
public string handleInput(InputKey key)
{
String state = determineState(key);
SomeType someResult = executeActionForState(state);
}
public String determineState(string key)
{
String state = "";
switch (key) {
case S:
case DOWN:
state = "cycleDown";
break;
case W:
case UP:
state = "cycleUp";
break;
case SPACE:
case ENTER:
state = "select";
break;
default:
break;
}
return state;
}
public void executeActionForState(string state)
{
if ( state == "cycleup" ) {
}
etc etc
}
Now, I may not necessarily code your example like this, this is a bit forced, it depends on what other things you're doing with the code, but this is meant to show how you separate functionality from UI aspects.
I can easily test the state method, I can change its code and I wouldn't have to change the test, because the test would look at the inputs and outputs and not how things are achieved.
Unit testing is about functionality, it's about having simple tests that don't need to change once created. Verifying that a method has been called doesn't give you anything worthwhile, because you don't know what that method does later.
UI stuff you can test in other ways, unit testing is only about correct functionality. If you do not make this separation clear then you will have trouble maintaining your tests, it will become harder and harder until you give up.
You would test that you get the correct state, then you test that cycleUp method does something correct based on your requirements and that's how you know each part works in isolation. Later on you start looking at integration tests, Automated UI tests, but those are different things. Keep unit testing for what it's meant to do, keep it simple, keep it not tied to other code and then everything becomes simple. You won't need to mock much, you won't need to worry too much about complex setups and you won't need to change your tests every time something in the code changes.
Now, to address the final part of the question, private methods, you test them by observing their outputs. You must have something public in your class that changes when a private method is called. So test that.
The rule squid:128 seems to exist to prevent fall-through in switch case unless explicitly stated. It seems a reasonable rule, as forgetting a break is a common mistake.
However fall-through are perfectly valid when wanted.
The Documentation of this rule states that the only way to achieve a fall-through is to use continue
case 4: // Use of continue statement
continue;
I have also checked the source code of SwitchCaseWithoutBreakCheck are the implementation really check for "continue" statement
#Override
public void visitContinueStatement(ContinueStatementTree tree) {
super.visitContinueStatement(tree);
markSwitchCasesAsCompliant();
}
However, the Java language does not support continue in switch/case. Nor the online documentation nor ./java-checks/src/test/files/checks/SwitchCaseWithoutBreakCheck.java are valid Java programs.
Am I missing something or is this rule fully broken and prevent using fall-through ?
You are totally right in saying that the description here is wrong and then you actually have no way to do not trigger the rule if you want to actually use fallthrough (and thus you might want either to mark issue as false positive in this case or deactivate the rule alltogether)
calling the rule "broken" is an opinion so I won't argue on that ;)
Nevertheless, a ticket has been created to handle the issue : http://jira.sonarsource.com/browse/SONARJAVA-1169
To me, the following Java code is perfectly valid, good style:
enum Side { LEFT, RIGHT };
...
Side side = ...;
switch (side) {
case LEFT:
// do something
break;
case RIGHT:
// do something
break;
}
For SonarQube’s rule SwitchLastCaseIsDefaultCheck, this is not good enough, it wants a default case. Now here, a default case is superfluous, since the enumeration is covered completely.
For enumerations, I would like to see a test that checks whether the enumeration is completely covered and complain if it is not covered and has no default case (Eclipse can do that). Either should be fine. In fact, completely covering an enumeration allows for a compile-time warning later when the enumeration is extended, while giving a default case will fail only at run-time.
Optionally, both completely covering the enumeration and giving a default case could trigger a warning for unreachable code.
I would suggest it is good practice to always include a default case which throws an appropriate RuntimeException. This way, you guard against a future developer adding something to the enum and forgetting to update the switch statement.
Eclipse is an IDE, it help you to develop the programs in a selected language here in your case it is JAVA, it doesn't do any thing which is not specified in language, so it is not the problem of eclipse, it is all about the specification of language.
As it turns out, three years after asking the question I find that squid:SwitchLastCaseIsDefaultCheck now checks for complete coverage of an enum. Probably has for some time now, at least for 4.4.0.8066 of the Java plugin from Sonarqube I can confirm that. And that’s a very satisfactory answer for me.
This is more of a design question.
Suppose you have a method like this (as an example):
if (x == 5) {
c = 1;
} else {
if (z != 2) {
b = 6;
} else {
a = 3;
}
Do you think it's best practice to have a junit for each possible branch? Ie, testx5, test xnot5znot2, testxnot5z2, etc, or something like:
void testMethod() {
// x is 5
test/assert code;
// x not 5, z not 2
test/assert code;
// x not 5, z is 2
test/assert code
// etc
}
EDIT: Just to be clear, my goal is complete code coverage. I just want to know opinions on whether I should make a new test for each branch or combine them in one test. Thank you for your input.
The JUnit FAQ seems to indicate that it is better to have more tests with fewer assertions, if only because JUnit will only report the first assertion failure in a test method. With one method, if you broke the x = 5 case, you'd have no way to tell if any of the x != 5 cases were still working.
What you're discussing is called Branch Coverage.
The conventional wisdom is if it's important enough to write code to cover that use case, it's important enough to write a test case to cover that code. So this would seem to say that 100% branch coverage is an excellent goal (and will also imply 100% statement coverage, but not necessarily 100% loop or 100% condition coverage).
However, you also need to balance the effort of writing tests with the value of getting those tests. For example, if the code you're testing has a try/catch to catch a checked exception, but the exception is almost never thrown (or difficult to cause to be thrown in a test case), then writing a test to cover that exception is probably not worth your time.
This is why you see in a lot of places that aiming for a certain % of test coverage is a bad idea, because you end up writing test cases to get coverage, not to find bugs. In your example, yes, each branch deserves it's own test case. In every piece of production code, it's probably not necessary.
In unit testing, your goal is to test behaviors -- not the "code". Think of the method you're testing a black box and you want to see if it works correctly. You don't know how it does it's job internally, but you expect certain results for certain inputs. So you'd want to create tests for different cases of how you'd expect the code to work as if you didn't know anything about how the internals of the method actually does it's job. So you'd write tests like "applysDiscountToShoppingCart" and "addsDeliveryFeeToShoppingCart".
Now, all that being said, it's also useful to create "edge cases" in which you're testing things that are likely to break (like nulls, zeros, negatives, data too big/small, etc) to see if it fails in an expected manner too. Usually to write those, you need to know how the method actually works. If you can design tests that will cover all your code, that's great! 100% test coverage is a definite thing to strive for, but it's not always practical (or useful) depending on the situation.
Especially on build servers it is easier to have many different testcases/functions because it will be easy to identify which test fails. Another downside is that the testcase will halt if the first one fails, and you will not know the result of the other testcases.
For me personally this benefit stops when you have to do a lot of copy pasting to set up/explain the testcase, in that case I will just do several asserts in the same test case.
For example, in a method
public void divide(Integer a){
//.....
}
In a Java test, we need to test a parameter as String, null, 0, Long .... , do we have a tool which will automatically test these all cases ?
Thanks
First, the compiler will not let you pass String nor Long so there's no point in unit-testing these.
Second, while there are some tools like the one you're describing, I wouldn't recommend them. Effective unit testing is not about trying to cover as much of the state space as possible (because the state space is infinitely large). It is about the wise choice of the "significant" cases. The one who decides what is considered to be significant is you, the programmer.
Well you can write this yourself using a JUnit TestCase. I don't know of any free tools which will automatically bombard it with all possible inputs to see how it will react, but I do know of the AgitarOne software product (commercial) which does this kind of testing. It's called agitation and lets you explore how your code behaves with nulls, max values, min values, etc.
Why not use JUnit 4 with a Parameterized test case? JUnit 3 did not support parameterized test cases OOTB, but JUnit 4 has specific API to accept arguments and invoke your test case using those parameters as input. Should that be feasible in your case?