Effective JUnit testing - java

I have a generel question about Unit testing. I have read some guides about unit testing, however i still have one question. What parts of my code do i have to test? For example the class bellow has some variables to be set and a list that is frequently filled, but does it make sense to test them in a JUnitClass? Which part would you test?
public class Bill implements interfaces.Bill {
int billNumber;
Set<Scanable> scans = new LinkedHashSet();
public Bill(int billNumber) {
this.billNumber = billNumber;
}
public void addItem(Scanable s) {
scans.add(s);
}
#Override
public float getSum() {
int sum = 0;
for(Scanable x : this.scans) {
sum += x.getPrice();
}
return sum;
}
#Override
public Set<Scanable> getItems() {
return scans;
}
}

i would at least write tests for
public void addItem(Scanable s){
scans.add(s);
}
#Override
public float getSum() {
int sum = 0;
for(Scanable x : this.scans){
sum+=x.getPrice();
}
return sum;
}
the reason is not primary to verify the current functionality, but more to be prepared for future changes. lets say, you decide at some point to not initialize the field scans directly and have the possibility to run into a NPE, then your tests should expose this and you can react quite fast.

In general, unit test is to test the logical function. Because those function will have side effect after you modify it.
If your getter and setter are just assign value and return value, there's no need to write your unit test.

I personally wouldn't write any unit tests for setters and getters, unless your setters() and getters() contain some programmatic business logic i.e. something getting computed when the setter()/getter() are called.
For rest others methods the UT cases are must.
In some companies, the code coverage is very strict and to adhere to the process, we may have to write UT for getters() & setters() also. Although its not a bad idea to always write :-)

Related

How to mock only a part of a function

I'm building an automatic game client that is supposed to make moves against me in a 4-Wins-Game. For making a move it should chose a column and send that chosen column by calling the move() function to my server.
public class AutomaticGameClient {
private String userName;
private String userPassword;
public AutomaticGameClient(String userName, String userPassword) {
this.userName = userName;
this.userPassword = userPassword;
}
public int makeMove() {
columnNo = 0;
move(columnNo);
return columnNo;
}
}
Right now it always simply moves by making the next move in the first row (columnNo = 0). This works.
Now I have to test that function, but I don't want to test the move() part. I only want to assert, that it's returning 0:
#Test
public void whenMakeMove_columnNoIsZero() {
AutomaticGameClient agcY = new AutomaticGameClient("Georg1", "geheim1");
int rowMoved = agcY.makeMove();
assertEquals(rowMoved, 0);
}
When I run this test, I get org.java_websocket.exceptions.WebsocketNotConnectedException, because move(columnNo) is trying to start a connection to my socket. So is there a way to skip this part of the function under test?
"So is there a way to skip this part of the function under test?" - Yes. One could create a partial mock/spy of the unit under test and then mock the move(...)-method. For more details please refer to this posts by Victor Grazi and its answers.
In this concrete situation, however, the cleaner solution would be to move socket-related code to a separate service. A unit should be tested as a unit and thus we should use mocks seldomly and only if no other possibility exists. This, however, is a boundary between units, thus socket-communication should be moved in a separate unit for better testability. Please notice that I do not say that each class is a unit. A unit can be composed of multiple classes. But one class should not be composed of multiple units since we then have to resort to solutions like partial mocks for the unit under test. In my opinion, mocking the unit under test is always a red flag.

How to validate overall execution of multiple JUnit 4 tests?

Desired: A "Test of the Tests"
Imagine there is some additional "sanity check" that could be performed after a test class completes all its tests that would indicate whether test execution as a whole executed successfully. This final sanity check could possibly use some aggregated information about the tests. Just as a crude example: The number of calls to a shared method is counted, and if the count is not above some minimum expected threshold after all tests complete, then it is clear that something is wrong even if all the individual tests pass.
What I have described is probably in some "grey area" of best practices because while it does violate the doctrine of atomic unit tests, the final sanity check is not actually testing the class being tested; rather, it is checking that test execution as a whole was a success: A "test of the tests," so-to-speak. It is additional logic regarding the tests themselves.
This Solution Seems Bad
One way to accomplish this "test of tests" is to place the sanity check in a static #AfterClass method. If the check fails, one can call Assert.fail(), which actually works (surprisingly, since I presumed it could only be invoked from within methods annotated with #Test, which by nature must be instance methods, not static):
public class MyTest {
[...]
#AfterClass
public static void testSufficientCount() {
if (MyTest.counterVariable < MIN_COUNT) {
Assert.fail("This fail call actually works. Wow.");
}
}
}
There are many reasons why this solution is a kludge:
Assume there are N tests in total (where a "test" is an instance method annotated with #Test). When Assert.fail() is not called in #AfterClass, N tests in total are reported by the IDE, as expected. However, when Assert.fail() is called in #AfterClass, N + 1 tests in total are reported by the IDE (the extra one being the static #AfterClass method). The additional static method was not annotated with #Test, so it should not be counted as a test. Further, the total number of tests should not be a function of whether some tests pass or fail.
The #AfterClass method is static by definition. Therefore, only static members are accessible. This presents a problem for my specific situation; I will leave this statement without elaboration because the explanation is out of the scope of the question, but basically it would be most desirable if only instance members were used.
[Other reasons too...]
Is There a Better Way?
Is there a way to implement this "test of tests" that is considered good and common practice? Does JUnit 4 support adding some kind of logic to ensure a group of unit tests within a class executed properly (failing in some way if they did not)? Is there a name for this thing I have called a "test of tests"?
About variable number of tests
I don't think there is a valid solution ...
About static fields
I tried to follow your example and, if I understood well, with a combination of Verifier, TestRule and ClassRule it is possible to use only the instance fields of the test class
Here my code from which to take a cue:
public class ATest {
public int countVariable = 0;
private static class MyVerifier extends Verifier {
public int count = 0;
#Override
protected void verify() throws Throwable {
assertTrue(count < 1); // cause new failed test
// assertTrue(count >= 1); // it's all ok
}
}
#ClassRule
public static MyVerifier v = new MyVerifier();
private class MyRule implements TestRule {
ATest a;
MyVerifier v;
public MyRule(ATest a, MyVerifier v) {
this.a = a;
this.v = v;
}
#Override
public Statement apply(Statement base, Description description) {
try {
base.evaluate();
this.v.count = a.countVariable;
} catch (Throwable ex) {
Logger.getLogger(ATest.class.getName()).log(Level.SEVERE, null, ex);
}
return base;
}
}
#Rule
public MyRule rule = new MyRule(this, v);
#org.junit.Test
public void testSomeMethod() {
countVariable++; // modifies instance counter
assertTrue(true);
}
#org.junit.Test
public void testSomeMethod2() {
countVariable++; // modifies instance counter
assertTrue(true);
}
}
Having said that
"test of tests" isn't consider a common and good practice because, as you know, it violates at least two of five principles of the FIRST rule(see Cleean code from Uncle Bob Martin): tests must be
F: Fast
I: Indipendent
R: Repeteable
S: Self-validating
T: Timely (linked to TDD practice)

How to test a method that uses Random(), without arguments and return value, using JUnit or Mockito

I'm studying to be a Java developer and right now I'm learning test driven development, which means that im very new to JUnit and Mockito.
I've been struggling for a while now and I'm stuck.
I have no idea how to test this particular method that has no arguments, no return value and a randomizer.
Old logic:
public void getPlayerToStart(int randomNr) {
if (randomNr == 1) {
currentPlayer = p1;
opponentPlayer = p2;
} else {
currentPlayer = p2;
opponentPlayer = p1;
}
}
Old test
#Test
void testSetCurrentPlayerSetToPlayer1() {
gameEngine.getPlayerToStart(1);
assertEquals(gameEngine.getP1(), gameEngine.getCurrentPlayer());
assertEquals(gameEngine.getP2(), gameEngine.getOpponentPlayer());
}
#Test
void testSetCurrentPlayerSetToPlayer2() {
gameEngine.getPlayerToStart(2);
assertEquals(gameEngine.getP2(), gameEngine.getCurrentPlayer());
assertEquals(gameEngine.getP1(), gameEngine.getOpponentPlayer());
}
New logic:
public void getPlayerToStart() {
Random rand = new Random();
int randomNr = rand.nextInt(2) + 1;
if (randomNr == 1) {
currentPlayer = p1;
opponentPlayer = p2;
} else {
currentPlayer = p2;
opponentPlayer = p1;
}
}
I'm not sure how to be able to test the getPlayerToStart() without the argument "randomNr".. Can someone please just point me in the right direction!
Thanks in advance.
Always to please be keeping in mind that the thought "gee, this is hard to test" is TDD trying to scream at you that the design needs review.
I have no idea how to test this particular method that has no arguments, no return value and a randomizer.
Random numbers are a side effect, like I/O or time, and should be handled that way in your design.
Which is to say, if you are doing TDD, one of the things you should be recognizing is that the source of randomness is an input to your system; it's part of the imperative shell which is provided by your test harness when running tests, and is provided by your composition root in production.
The testable approach would separate "generate a seed" from "compute a state from the seed"; unit tests are great for the latter bit, because pure functions are really easy to test. Generating random numbers is state of sin level hard to test, but with some design you can simplify the code around it to the point that it "obviously has no deficiencies".
You may also want to review Writing Testable Code, by Misko Hevery, or Tales of the Fischer King.
another solution could be a strict interpretation of the single responsibility pattern: a class providing business logic sould not be responsible to create or acquire its dependencies. This leads to the concept of dependency injection:
class CodeUnderTest {
private final Random rand;
public CodeUnderTest(#NotNull Random rand){
this.rand = rand;
}
public void getPlayerToStart() {
int randomNr = rand.nextInt(2) + 1;
if (randomNr == 1) {
currentPlayer = p1;
opponentPlayer = p2;
} else {
currentPlayer = p2;
opponentPlayer = p1;
}
}
}
You'd need to enhance your Test to this:
class CodeUnderTestTest{
private final Random fakeRandom = new Random(1);
private CodeUnderTest cut;
#Before
public void setup(){
cut = new CodeUnderTest(fakeRandom);
}
// your test code relying on the repeatable order
// of Random object initialized with a fix seed.
}
You also need to change all places in your code where you instantiate CodeUnderTest to add a Random object without seed.
This looks like a downside at first but it provides the possibility to have only one instance of Random throughout your code without implementing the Java Singelton Pattern.
You could gain even more control if you replace the Random object with a mock. The easiest way to do that is to use a mocking framework like Mockito:
class CodeUnderTestTest{
#Rule
public MockitoRule rule = MockitoJUnit.rule();
#Mock
private Random fakeRandom;
// you could use #InjectMocks here
// instead of the setup method
private CodeUnderTest cut;
// This will NOT raise compile errors
// for not declared or not provided
// constructor arguments (which is bad in my view).
#Before
public void setup(){
cut = new CodeUnderTest(fakeRandom);
}
#Test
void testSetCurrentPlayerSetToPlayer1() {
doReturn(0).when(fakeRandom).nextInt(2);
cut.getPlayerToStart(1);
assertEquals(cut.getP1(), cut.getCurrentPlayer());
assertEquals(cut.getP2(), cut.getOpponentPlayer());
}
}
Move the call to new Random() into its own method, like this.
You can rewrite your getPlayerToStart method to use the other one, to save duplicated code (but you don't need to).
public void getPlayerToStart() {
Random rand = makeRandom();
int randomNumber = rand.nextInt(2) + 1
getPlayerToStart(randomNumber);
}
public Random makeRandom() {
return new Random();
}
Now you can use Mockito to
make a mock Random object;
make a spy of your class, which is the object you're going to test;
stub the makeRandom method of your spy, so that it returns your mock Random;
stub the mock Random so that it returns whichever value you like, in each test.
After that, you can write a test in which player 1 is expected to start, and another test in which player 2 is expected to start.
I agree with who says that you should use dependency injection and have your own abstraction (in this way you could mock the collaborator).
But, creating the abstraction you're simply moving the responsibility (and the test problem) elsewhere.
Did you know about the Random constructor that takes an integer argument called "seed"? Using the same seed you will have always the same sequence of results.
See: https://stackoverflow.com/a/12458415/5594926

when return value from a method,assign that value to a variable first and return that variable is better than return value directly?

When we return value from a method,assign the return value to a variable is better than return value directly without assign to any variable?in the following examples:
public int getCustomerId(){
return CustomerService.getCustomerById();
}
and another example:
public int getCustomerId(){
int id = CustomerService.getCustomberById();
return id;
}
which one is more better and why?I saw one of my friend's code,he assign value to variable first and then return that variable to his service method.
Both the approach are right, it's all depend how much code we are writing in our functions or how much readable our code is.
If it is one-two liner code, i would go for the first approach.
As simple as this, readability is fine.
public int getCustomerId(){
return CustomerService.getCustomerById();
}
This makes code little less readable, because just a service call, i need to go through two steps. Extra debugging.
public int getCustomerId(){
int id = CustomerService.getCustomberById();
return id;
}
If i have some complex logic written, maybe at business layer, multiple if-else, try-catch etc, then 2nd approach looks fine.
Just an example, and it makes sense
f(){
Object obj = null;
try{
if(condition){
obj = // call service1
}else {
obj = // call service2
}
}catch(Exception e){
}
return obj;
}
I agree using extra variable (though local to function), then
assignment, might add little overhead to JVM, but code readability
should also be considered while coding. JVM is again smart enough to optimize your code as highlighted above.
Refer these links for something more. Not exactly related but can help.

Resources for JUnit testing of a class

As an exercise, I need to learn to write tests on the following class:
package bankAccount;
public class CurrentAccount {
int account[];
int lastMove;
CurrentAccount() {
lastMove = 0;
account = new int[10];
}
public void deposit(int value) {
account[lastMove] = value;
lastMove++;
}
public void draw(int value) {
account[lastMove] = value;
lastMove++;
}
public int settlement() {
int result = 0;
for (int i=0; i<account.length; i++) {
result = result + account[i];
}
return result;
}
public static void main(String args[]) {
CurrentAccount c = new CurrentAccount();
c.deposit(10);
}
}
I am relatively new to Unit testing, and a lot of the tutorials simply cover how to do tests for simple Mathematical operators (e.g. add, subtract etc). Can anyone recommend good resources for doing Unit testing of more complex functions? Am I best off using
http://junit.sourceforge.net/javadoc/org/junit/Assert.html
and working from there?
You should be testing against the specification of the object e.g.
what's the starting balance ?
what's the balance after I add £10 ?
can I go overdrawn ?
etc. All the above should be specified prior to writing the class (otherwise, how do you know what to write?)
I would create a test method for each of these scenarios, perform a setup and the action, and then use one (or more, if necessary) asserts to determine that all is well. Don't forget that in some cases you may be testing that an exception is thrown, and consequently you will want to check for a break in control flow. That wouldn't use assert.
Here's a possible example (imports etc. omitted)
public void testBalanceAfterTenPoundDeposit() {
// note the interface/impl separation so I can test different
// implementations with the same interface (this is Test By Contract)
CurrentAccount ca = new CurrentAccountImpl();
// check the starting balance
Assert.assertEquals(ca.settlement(), 0);
// deposit
ca.deposit(10);
// do I have £10 ?
Assert.assertEquals(ca.settlement(), 10);
}
It's important to note that this sort of testing should really be focused on the component (unit) as a black box. That is, the test should really be agnostic to the implementation and you wouldn't explicitly test the array implementation. I should be able to insert my own implementation (or rewrite yours) and the tests should remain working (that's the principle of a regression test).
Having said that, if you know of obvious limitations of the implementation (e.g. your fixed size array) you should try and stress that (e.g. in this situation, perform 11 inserts)

Categories

Resources