Chapter Four - Work with Other Classes
In this chapter you are going to learn how to use other classes in your @Test method code. Eventually these will be classes that you write, but for the moment we will use other classes that are built in to Java.
You have already done this in the previous chapter. Because you used the JUnit Assert class to check conditions, but we imported it statically, so you might not have noticed. (I’ll explain what static import means in the next chapter).
But first, some guidance on how to learn Java.
Use @Test methods to understand Java
When I work with people learning Java, I encourage them to write methods and assertions which help them understand the Java libraries they are using. And that is what we will do in this chapter.
For example, you have already seen a primitive type called an int.
Java also provides a class called Integer.
Because Integer is a class, it has methods that we can call, and we can instantiate an object variable as an Integer.
When I create an int variable, all I can do with it, is store a number in the variable, and retrieve the number.
If I create an Integer variable, I gain access to a lot of methods on the integer e.g.
-
compareTo- compare it to another integer -
intValue- return anintprimitive -
longValue- return alongprimitive -
shortValue- return ashortprimitive
Explore the Integer class with @Test methods
In fact you can see for yourself the methods available to an integer.
- Create a new package:
com.javafortesters.chap004testswithotherclasses.examples
- Create a new class
IntegerExamplesTest - Create a method
integerExploration - Annotate the method with
@Testso you can run it with JUnit
You should end up with something like the following:
package com.javafortesters.chap004testswithotherclasses.examples;
import org.junit.Test;
public class IntegerExamplesTest {
@Test
public void integerExploration(){
}
}
We can use the integerExploration method to experiment with the Integer class.
Instantiate an Integer Class
The first thing we need to do is create a variable of type Integer.
Integer four = new Integer(4);
Because Integer is a class, this is called instantiating a class and the variable is an object variable.
-
intwas a primitive type. -
Integeris a class. - To use a class we instantiate it with the
newkeyword - The
newkeyword creates a new instance of a class - The new instance is referred to as an object or an instance of a class
You can also see that I passed in the literal 4 as a parameter. I did this because the Integer class has a constructor method which takes an int as a parameter so the object has a value of 4.
The Integer class actually has more than one constructor. You can see this for yourself.
- Type in the statement to instantiate a new
Integerobject with the value4 - Click inside the parentheses where the
4is, as if you were about to type a new parameter, - press the keys
ctrl + p(cmd + pon a Mac)
You should see a pop-up showing you all the forms the constructor can take. In the case of an Integer it can accept an int or a String.
Check that intValue returns the correct int
We know that the Integer class has a method intValue which returns an int, so we can create an assertion to check the returned value.
After the statement which instantiates the Integer.
Add a new statement which asserts that intValue returns an int with the value 4.
assertEquals("intValue returns int 4",
4, four.intValue());
When you run this method it should pass.
Instantiate an Integer with a String
We saw that one of the constructors for Integer can take a String, so lets write some code to experiment with that.
- Instantiate a new
Integervariable, calling theIntegerconstructor with theString"5", - Assert that
intValuereturns theInteger5
Integer five = new Integer("5");
assertEquals("intValue returns int 5",
5, five.intValue());
Quick Summary
package com.javafortesters.chap004testswithotherclasses.examples;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class IntegerExamplesTest {
@Test
public void integerExploration(){
Integer four = new Integer(4);
assertEquals("intValue returns int 4",
4, four.intValue());
Integer five = new Integer("5");
assertEquals("intValue returns int 5",
5, five.intValue());
Integer six = 6;
assertEquals("autoboxing assignment for 6",
6, six.intValue());
}
}
It might not seem like it but we just covered some important things there.
- Did you notice that you didn’t have to
importtheIntegerclass?- Because the
Integerclass is built in to the language, we can just use it. There are a few classes like that,Stringis another one. The classes do exist in a package structure, they are injava.lang, but you don’t have toimportthem to use them.
- Because the
- We just learned that to use an object of a class, that someone else has provided, or that we write, we have to instantiate the object variables using the
newkeyword. - Use
ctrl + pto have the IDE show you what parameters a method can take (cmd + pon a Mac). - When we instantiate a class with the
newkeyword, a constructor method on the class is called automatically.
AutoBoxing
In the versions of Java that we will be using, we don’t actually need to instantiate the Integer class with the new keyword.
We can take advantage of a Java feature called ‘autoboxing’ which was introduced in Java version 1.5. Autoboxing will automatically convert from a primitive type to the associated class automatically.
So we can instead simply assign an int to an Integer and autoboxing will take care of the conversion for us e.g.
Integer six = 6;
assertEquals("autoboxing assignment for 6",
6, six.intValue());
Static methods on the Integer class
Another feature that classes provide are static methods.
You already used static methods on the Assert class from JUnit. i.e. assertEquals
A static method operates at the class level, rather than the instance or object level. Which means that we don’t have to instantiate the class into a variable in order to call a static method.
e.g. Integer provides static methods like:
-
Integer.valueOf(String s)- returns anIntegerinitialized with the value of theString -
Integer.parseInt(String s)- returns anintinitialized with the value of theString
You can see all the static methods by looking at the documentation for Integer, or in your code write Integer. then immediately after typing the . the IDE should show you the code completion for all the static methods.
For each of these methods, if you press ctrl + q (ctrl + j on a Mac) you should see the help file information for that method.
Public Constants on the Integer class
It is possible to create variables at a class level (these are called fields) which are also static. These field variables are available without instantiating the class. The Integer class exposes a few of these but the most important ones are MIN_VALUE and MAX_VALUE.
In addition to being static fields, these are also constants, in that you can’t change them. (We’ll cover how to do this in a later chapter). The naming convention for constants is to use only uppercase, with _ as the word delimiter.
MIN_VALUE and MAX_VALUE contain the minimum and maximum values that an int can support. It is worth using these values instead of -2147483648 and 2147483647 to ensure future compatibility and cross platform compatibility.
To access a constant, you don’t need to add parenthesis because you are accessing a variable, and not calling a method.
i.e. you write “Integer.MAX_VALUE” and not “Integer.MAX_VALUE()”.
Do this regularly
I encourage you to do the following regularly.
When you encounter:
- any Java library that you don’t know how to use
- parts of Java that you are unsure of
- code on your team that you didn’t write and don’t understand
Then you can:
- read the documentation -
ctrl + q(ctrl + jon Mac) or on-line web docs - read the source -
ctrland click on the method, to see the source - write some
@Testannotated methods, with assertions, to help you explore the functionality of the library
When writing the @Test methods you need to keep the following in mind:
- write just enough code to trigger the functionality
- ensure you write assertion statements that cover the functionality well and are readable
- experiment with ‘odd’ circumstances
This will help you when you come to write assertions against your own code as well.
Warnings about Integer
I used Integer in this chapter because we used the int primitive in an earlier chapter and Integer is the related follow on class.
But… experienced developers will now be worried that you will start using Integer in your code, and worse, instantiating new integers in your code e.g. new Integer(0)
They worry because while an int equals an int, an Integer does not always equal an Integer.
I’m less worried because:
- I trust you,
- Automation code has slightly different usages than production code and you’ll more than likely use the
Integerstaticmethods - I’m using this as an example of instantiating a class and using static methods,
- This is only “Chapter 4” and we still have a way to go
I’ll illustrate with a code example, why the experienced developers are concerned. You might not understand the next few paragraphs yet, but I just want to give you a little detail as to why one Integer, or one Object, does not always equal another Object.
e.g. if the following assertions were in an @Test method then they would pass:
assertEquals(4,4);
assertTrue(4==4);
Note that “==” is the Java operator for checking if one thing equals another.
If the following code was in an @Test method, then the second assertion would fail:
Integer firstFour = new Integer(4);
Integer secondFour = new Integer(4);
assertEquals(firstFour, secondFour);
assertTrue(firstFour==secondFour);
Specifically, the following assertion would fail:
assertTrue(firstFour==secondFour);
Why is this?
Well, primitives are simple and there is no difference between value and identity for primitives. Every 4 in the code refers to the same 4.
Objects are different, we instantiate them, so the two Integer variables (firstFour and secondFour) both refer to different objects. Even though they have the same ‘value’, they are different objects.
When I do an assertEquals, JUnit uses the equals method on the object to compare the ‘value’ or the object (i.e. 4 in this case). But when I use the "==" operator, Java is checking if the two object variables refer to the same instantiation, and they don’t, they refer to two independently instantiated objects.
So the assertEquals is actually equivalent to:
assertTrue(firstFour.equals(secondFour));
Don’t worry if you don’t understand this yet. It will make sense later.
For now, just recognize that:
- you can create object instances of a class with the
newkeyword, and use the non-static methods on the class e.g.anInteger.intValue() - you can access the
staticmethods on the class without instantiating the class as an object e.g.Integer.equals(..).
Summary
You learned that in IntelliJ you can press ctrl and then the left mouse button to click on a method name and IntelliJ will jump to the source of that method.
You learned the following shortcut keys:
| Function | Windows | Mac |
|---|---|---|
| Show Parameters | ctrl + p |
cmd + p |
| Show JavaDoc | ctrl + q |
ctrl + j |
You also learned about static methods and the difference between object value and object identity.
Whatever you learn in this book, make sure you continue to experiment with writing assertions around code that you use or want to understand.
You also learned how to instantiate a new object and what a constructor does.