Testing with JUnit a void method - java

I have the following code, and I dont know how to test it.
I was trying to access the count contD++, and if i have 3 negatives.
I cant test it with something like this assertEquals(contD,3)
public void listarD() {
int contD = 0;
for(int i=0; i< clientes.length; i++) {
if(clientes[i].getSaldo() < 0) {
System.out.println(
"Cliente: " + clientes[i].getNombre() +
". Saldo: " + clientes[i].getSaldo());
contD++;
}
}
if (contD == 0) {
System.out.println("No hay descubiertos :D");
}
else {
System.out.println("TOTAL DESCUBIERTOS: " + contadorDescubiertos + " clientes");
}
}

Correct way would be to extract a method that calculates your contD value and test it.
public void listarD() {
int contD = calculateContD();
if (contD == 0) {
...
}
}
And then you can test this calculateContD() method.

A well designed method should be easy to test, the fact that you cannot test your method is an evidence of a design flaw.
Some suggestions:
Make the result of the method verifiable (That could imply that it's
no longer void).
Leave the output on a permanent storage, like disk
or database.

There is one way you could theoretically test this: one can change the object behind System.out.
So, theoretically, you could put a "special" OutputStream into System.out; run your void method; and then check that the messages you would expect ... show up in that stream of yours.
But that simply makes no (t much) sense: you see, in the real world, you rarely do print to system.out. In the real world, your methods either
do return a value
make calls on other objects
change some internal state of the enclosing object/class
Thus: in the real world, you write tests that care about such kind of events.
So, as you figured yourself; the real answer is to change the behavior of your void method; by returning the value it computed already!

In general, a function that can only be verified by human eyes is not a good design. Callers would never know what happened after they call your function. Either a return value or an exception for denoting the result is better than nothing.

Related

How to use correctly assertThrows on set of values?

I've been learning Java just for a bit, so please advise how exception throwing test should look like in this case?
I have following Gambling Machine Class. And then 2 tests for it. I do not really know what should follow the "Integer" in second method (shouldThrowWhenNumbersOutOfRange). Could you please advise as to the exact syntax?
public class GamblingMachine {
public int howManyWins(Set<Integer> userNumbers) throws InvalidNumbersException {
validateNumbers(userNumbers);
Set<Integer> computerNumbers = generateComputerNumbers();
int count = 0;
for (Integer number : userNumbers) {
if (computerNumbers.contains(number)) {
count++;
}
}
return count;
}
private void validateNumbers(Set<Integer> numbers) throws InvalidNumbersException {
if (numbers.size() != 6) {
throw new InvalidNumbersException();
}
if (numbers.stream().anyMatch(number -> number < 1 || number > 49)) { //anyMatch-function to check whether any element in list satisfy given condition
throw new InvalidNumbersException();
}
}
private Set<Integer> generateComputerNumbers() {
Set<Integer> numbers = new HashSet<>();
Random generator = new Random();
while(numbers.size() < 6) {
numbers.add(generator.nextInt(49) + 1);
}
return numbers;
}
}
private GamblingMachine machine = new GamblingMachine();
#ParameterizedTest
#NullAndEmptySource
public void shouldThrowWhenNumbersEmpty(Set<Integer> numbers) throws InvalidNumbersException {
Assertions.assertThrows(NumberFormatException.class, () -> {
Integer.parseInt(" ");
});
}
#ParameterizedTest
#CsvFileSource(resources ="/numbersOutOfRange.cvs", numLinesToSkip = 1)
public void shouldThrowWhenNumbersOutOfRange(Set<Integer> numbers) throws InvalidNumbersException {
Assertions.assertThrows(NumberFormatException.class, () -> {
Integer. //how code should look like here?
});
}
The point of a test is to, you know, test something. Your shouldThrowWhenNumbersEmpty test doesn't do that (well, it tests that Integer.parseInt(" ") throws something. It does, of course. You... don't have to test the core libraries).
In other words, your gambling machine tests need to be calling some stuff from your GamblingMachine class. The idea is to test GamblingMachine. Not to test Integer.parseInt.
It's also a bizarre test: Why in the blazes is shouldThrowWhenNumbersEmpty parameterized? I assume the point of that test is: "Ensure that the gambling machine works as designed when passing an empty set of numbers in, specifically, the part of the design that states that an InvalidNumbersException is thrown if you do that".
Which is done with something like:
#Test
public void shouldThrowWhenNumbersEmpty() {
Assertions.assertThrows(InvalidNumbersException.class, () -> {
Set<Integer> empty = Set.of();
machine.howManyWins(empty);
});
}
Parameterized tests are a fairly exotic concept. Your test setup appears to be falling into a trap: It appears to be set up that you repeat all the logic that is already in your gamblingmachine class, to then apply this logic to the incoming (parameterized) data, figure out what your gambling machine ought to be doing, and then double check its work.
That's not how you should write tests. Tests focus on a specific result. Parameterized tests can make sense, but only if the stuff you have to do for any given input is roughly the same. For example:
Good use of parameterized testing
You have a csv file containing a bunch of lines, each of which has 6 rolls + the correct answer. Your parameterized test treats each line the same: Call howManyWins using the 6 rolls as input, then check that howManyWins returns the expected value.
Bad use of parameterized testing
You have a csv file containing a bunch of lines, each of which has 6 rolls. Your parameterized test will calculate the right result for the rolls, then invoke gambling machine, and check that the gambling machine gives the same answer as what you calculated.
This is bad: You're just repeating the code. It also means your test code is itself doing more than the very basics (it's doing a bunch of business logic), thus raising the question: Who tests your test, then?
Both of your test methods seem like they should NOT be parameterized, unless that csv also contains results.

Identify record that is culprit - coding practices

Is method chaining good?
I am not against functional programming that uses method chaining a lot, but against a herd mentality where people mindlessly run behind something that is new.
The example, if I am processing a list of items using stream programming and need to find out the exact row that resulted into throwing NullPointerException.
private void test() {
List<User> aList = new ArrayList<>();
// fill aList with some data
aList.stream().forEach(x -> doSomethingMeaningFul(x.getAddress()));
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
So in the example above if any object in list is null, it will lead to NullPointerException while calling x.getAddress() and come out, without giving us a hook to identify a User record which has this problem.
I may be missing something that offers this feature in stream programming, any help is appreciated.
Edit 1:
NPE is just an example, but there are several other RuntimeExceptions that could occur. Writing filter would essentially mean checking for every RTE condition based on the operation I am performing. And checking for every operation will become a pain.
To give a better idea about what I mean following is the snippet using older methods; I couldn't find any equivalent with streams / functional programming methods.
List<User> aList = new ArrayList<>();
// Fill list with some data
int counter = 0;
User u = null;
try {
for (;counter < aList.size(); counter++) {
u = aList.get(counter);
u.doSomething();
int result = u.getX() / u.getY();
}
} catch(Exception e) {
System.out.println("Error processing at index:" + counter + " with User record:" + u);
System.out.println("Exception:" + e);
}
This will be a boon during the maintenance phase(longest phase) pointing exact data related issues which are difficult to reproduce.
**Benefits:**
- Find exact index causing issue, pointing to data
- Any RTE is recorded and analyzed against the user record
- Smaller stacktrace to look at
Is method chaining good?
As so often, the simple answer is: it depends.
When you
know what you are doing
are be very sure that elements will never be null, thus the chance for an NPE in such a construct is (close to) 0
and the chaining of calls leads to improved readability
then sure, chain calls.
If any of the above criteria isn't clearly fulfilled, then consider not doing that.
In any case, it might be helpful to distribute your method calls on new lines. Tools like IntelliJ actually give you advanced type information for each line, when you do that (well, not always, see my own question ;)
From a different perspective: to the compiler, it doesn't matter much if you chain call. That really only matters to humans. Either for readability, or during debugging.
There are a few aspects to this.
1) Nulls
It's best to avoid the problem of checking for nulls, by never assigning null. This applies whether you're doing functional programming or not. Unfortunately a lot of library code does expose the possibility of a null return value, but try to limit exposure to this by handling it in one place.
Regardless of whether you're doing FP or not, you'll find you get a lot less frustrated if you never have to write null checks when calling your own methods, because your own methods can never return null.
An alternative to variables that might be null, is to use Java 8's Optional class.
Instead of:
public String myMethod(int i) {
if(i>0) {
return "Hello";
} else {
return null;
}
}
Do:
public Optional<String> myMethod(int i) {
if(i>0) {
return Optional.of("Hello");
} else {
return Optional.empty();
}
Look at Optional Javadoc to see how this forces the caller to think about the possibility of an Optional.empty() response.
As a bridge between the worlds of "null represents absent" and "Optional.empty() represents absent", you can use Optional.ofNullable(val) which returns Empty when val == null. But do bear in mind that Optional.empty() and Optional.of(null) are different values.
2) Exceptions
It's true that throwing an exception in a stream handler doesn't work very well. Exceptions aren't a very FP-friendly mechanism. The FP-friendly alternative is Either -- which isn't a standard part of Java but is easy to write yourself or find in third party libraries: Is there an equivalent of Scala's Either in Java 8?
public Either<Exception, Result> meaningfulMethod(Value val) {
try {
return Either.right(methodThatMightThrow(val));
} catch (Exception e) {
return Either.left(e);
}
}
... then:
List<Either<Exception, Result>> results = listOfValues.stream().map(meaningfulMethod).collect(Collectors.toList());
3) Indexes
You want to know the index of the stream element, when you're using a stream made from a List? See Is there a concise way to iterate over a stream with indices in Java 8?
In your test() function you are creating an emptylist List<User> aList = new ArrayList<>();
And doing for each on it. First add some element to
aList
If you want to handle null values you can add .filter(x-> x != null) this before foreach it will filter out all null value
Below is code
private void test() {
List<User> aList = new ArrayList<>();
aList.stream().filter(x-> x != null).forEach(x -> doSomethingMeaningFul(x.getAddress()));
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
You can write a black of code in streams. And you can find out the list item which might result in NullPointerException. I hope this code might help
private void test() {
List<User> aList = new ArrayList<>();
aList.stream().forEach(x -> {
if(x.getAddress() != null)
return doSomethingMeaningFul(x.getAddress())
else
system.out.println(x+ "doesn't have address");
});
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
If you want you can throw NullPointerException or custom excption like AddressNotFoundException in the else part

toString blocking my main

I've nearly got this Java program working 100% as intended, but my toString method is causing the whole system to break down... apparently. Here are the two pieces of code which seem to be clashing.
public class Main
{
public static void main()
{
Ground ground = new Ground();
ground.play();
}
}
that's the main function. fairly basic stuff. here's the play function:
public void play()
{
int i = 0;
System.out.println(Ground.toString());
while(i < 100 && isChestUnlocked() == false)
{
turn();
System.out.println(Ground.toString());
++i;
}
System.out.print("You unlocked the treasure!");
}
When I try to use it like this, bluej spits the dummy at me and claims that toString can't be referenced in a static context. How can I fix this? It feels like one of those "two characters are wrong" questions, and it's driving me nuts.
EDIT: If I change the Ground.toStrings to ground.toStrings, it claims it can't find the variable ground.
EDIT EDIT: Though I could swear it didn't work before, apparently this.toStrings works now. Thanks to ratchet for that!
remove the Ground or replace with this.
public void play()
{
int i = 0;
System.out.println(this.toString());
while(i < 100 && isChestUnlocked() == false)
{
turn();
System.out.println(this.toString());
++i;
}
System.out.print("You unlocked the treasure!");
}
Ground means the class while this is the current object the method is running on.
In fact just doing System.out.println(this); will work just as well. The println(Object) overload of System.out will invoke toString on the passed in object.
System.out.println(Ground.toString());
This calls toString() on the class rather than the object, which would require a static toString() which likely does not exist.
You need to change all instances of Ground.toString() to this.toString() or simply toString(), referring to the instance rather than the class.

Is there a way to test for enum value in a list of candidates? (Java)

This is a simplified example. I have this enum declaration as follows:
public enum ELogLevel {
None,
Debug,
Info,
Error
}
I have this code in another class:
if ((CLog._logLevel == ELogLevel.Info) || (CLog._logLevel == ELogLevel.Debug) || (CLog._logLevel == ELogLevel.Error)) {
System.out.println(formatMessage(message));
}
My question is if there is a way to shorten the test. Ideally i would like somethign to the tune of (this is borrowed from Pascal/Delphi):
if (CLog._logLevel in [ELogLevel.Info, ELogLevel.Debug, ELogLevel.Error])
Instead of the long list of comparisons. Is there such a thing in Java, or maybe a way to achieve it? I am using a trivial example, my intention is to find out if there is a pattern so I can do these types of tests with enum value lists of many more elements.
EDIT: It looks like EnumSet is the closest thing to what I want. The Naïve way of implementing it is via something like:
if (EnumSet.of(ELogLevel.Info, ELogLevel.Debug, ELogLevel.Error).contains(CLog._logLevel))
But under benchmarking, this performs two orders of magnitude slower than the long if/then statement, I guess because the EnumSet is being instantiated every time it runs. This is a problem only for code that runs very often, and even then it's a very minor problem, since over 100M iterations we are talking about 7ms vs 450ms on my box; a very minimal amount of time either way.
What I settled on for code that runs very often is to pre-instantiate the EnumSet in a static variable, and use that instance in the loop, which cuts down the runtime back down to a much more palatable 9ms over 100M iterations.
So it looks like we have a winner! Thanks guys for your quick replies.
what you want is an enum set
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumSet.html
put the elements you want to test for in the set, and then use the Set method contains().
import java.util.EnumSet;
public class EnumSetExample
{
enum Level { NONE, DEBUG, INFO, ERROR };
public static void main(String[] args)
{
EnumSet<Level> subset = EnumSet.of(Level.DEBUG, Level.INFO);
for(Level currentLevel : EnumSet.allOf(Level.class))
{
if (subset.contains(currentLevel))
{
System.out.println("we have " + currentLevel.toString());
}
else
{
System.out.println("we don't have " + currentLevel.toString());
}
}
}
}
There's no way to do it concisely in Java. The closest you can come is to dump the values in a set and call contains(). An EnumSet is probably most efficient in your case. You can shorted the set initialization a little using the double brace idiom, though this has the drawback of creating a new inner class each time you use it, and hence increases the memory usage slightly.
In general, logging levels are implemented as integers:
public static int LEVEL_NONE = 0;
public static int LEVEL_DEBUG = 1;
public static int LEVEL_INFO = 2;
public static int LEVEL_ERROR = 3;
and then you can test for severity using simple comparisons:
if (Clog._loglevel >= LEVEL_DEBUG) {
// log
}
You could use a list of required levels, ie:
List<ELogLevel> levels = Lists.newArrayList(ELogLevel.Info,
ELogLevel.Debug, ELogLevel.Error);
if (levels.contains(CLog._logLevel)) {
//
}

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.

Categories