More Java
Airport Challenge
Yesterday we started work on re-creating another old challenge in Java, the Airport Challenge. We had to use TDD to write the code from the start, using JUnit. This was a bit more difficult than the first two times we have done it, as Java is way less friendly, and JUnit is even worse! By lunch time however we had got it to the same point as we got the JavaScript one last time, so we were happy with our progress. One notable difference was the difficulty in using ‘doubles’ or mocking in Java. In Ruby you could double a class and its methods, in JS you could use spy objects and spy on classes to insert methods, but there is nothing like that in Java. There is a library for JUnit called Mockito however:
Mockito
According to the Mockito website;
Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with a clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors.
I am not so sure I agree with that at the moment, it seems like it isn’t easy to use or read, however it is apparently the easiest of the mocking frameworks in Java, so I would hate to see any others! To mock a class you do:
Plane mockedPlane = mock(Plane.class);
// and you can stub methods too
when(mockedPlane.land()).thenReturn(true);
Trying to use this in the JUnit tests is not as easy as doubles or spy objects, but I am hoping we will get the hang of it soon!
Airport Challenge Continued…
Unfortunately for the moment, I still don’t know the best way to use Mockito, so I got around some of the problems in different ways. For example, in the airport challenge, one of the user stories states that a plane should now be able to take off or land when the weather is stormy. To accomplish this we have a Weather class with a method that generates a random number between 1 and 100, and if it is above 95, we say the weather is stormy, giving it a 5% chance. In Ruby and JS we would double/spy on this Weather class so we could set it either way when testing, allowing us to always be able to test in the right conditions, rather than relying on random chance. I tried doing the same with Mockito but couldn’t get it to work. Instead, in my Airport class, I created a boolean variable called weather:
public boolean weather = Weather.isStormy();
This variable ran my Weather method, which returns True or False depending on the random number, and stores it in a weather boolean variable.
Boolean – not sure I have actually explained what a boolean is before, basically boolean means True or False, nothing else.
Then in my methods further down the airport class I can return an error if the weather variable is true:
public Object clearForLanding(Plane plane) {
if(weather){
return "Can't land in a storm";
}
return planes.add(plane);
}
This all works, and also means that in my test, I can just set the variable at the beginning to whatever I need it to be, even changing it mid test:
@Test
void cannotTakeOffStorm(){
airport.weather = false;
airport.clearForLanding(mockedPlane);
airport.weather = true;
assertEquals("Can't take off in a storm", airport.clearForTakeOff(mockedPlane));
}
JUnit
JUnit is not my nickname, JUnit is the testing framework we are using for Java. I mentioned it yesterday, but I will give a bit more detail about how the tests work today.
Here is an example of a simple test class with one test:
package AirportChallenge;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class AirportTest {
Airport airport = new Airport();
Plane mockedPlane = mock(Plane.class);
@Test
void planesCanLandAtAirport() {
airport.weather = false;
airport.clearForLanding(mockedPlane);
assertEquals(1, airport.getPlanes().size());
}
}
I will break it down and explain what each bit means:
package AirportChallenge;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
The bits at the top just tell the test class what stuff it needs. package is the folder that contains all the classes we are working on together. The import bits are different libraries we are using, JUnit and Mockito. We have to import the JUnit library into our file so IntelliJ knows to use it.
class AirportTest {
Airport airport = new Airport();
Plane mockedPlane = mock(Plane.class);
class AirportTest is the class we are writing our tests in. It is created by taking the name of the class we want to test, and adding ‘Test’. The two bits underneath are us declaring our class objects. Airport we are creating a new class object for, and Plane we are creating a mocked class with Mockito.
@Test
void planesCanLandAtAirport() {
airport.weather = false;
airport.clearForLanding(mockedPlane);
assertEquals(1, airport.getPlanes().size());
}
@Test tells IntelliJ that this is a test, which means we can use different pre-written methods from the JUnit library, such as assertEquals.void planesCanLandAtAirport() is the name of our test. Void in Java means that the method doesn’t return anything, which is always true for tests.airport.weather = false; and airport.clearForLanding(mockedPlane); are set up for the test. I am setting my weather to not be stormy, and then landing my mockedPlane class instance object at the airport.
Finally assertEquals(1, airport.getPlanes().size()); is the actual test. It is checking that the two things I have put in are equal. In this case, it is checking that the size of my planes array (which is retrieved with getPlanes()) is 1, as my plane should now have landed at the airport and been put in the array.
Spanish
Just in case anyone was wondering, I am still going with the Spanish lessons on Duolingo. I am on a 36 day streak, haven’t missed one since I started! I have done at least one level on 30 different topics now, so making some progress. I can’t really speak any Spanish, but I am getting a lot better at reading it and recognising words!

Spring Boot and Thymeleaf
In the afternoon we started to look at Spring boot and Thymeleaf, but I will go into more detail on those tomorrow, when hopefully I understand it better!
Todays song of the day:

