Using JUnit Rules to simplify your tests

Have you ever wrote JUnit tests exteding a class that does some before and after work, so you didn't have to repeat that code in various test classes? Well, I will not say that you have been doing it wrong, but, sure enough, you could do it better. How? Using JUnit Rules!

The Basics

Well, before we learn all that, let's start with the basics, shall we?

Timeouts

Let's take a simple example: Suppose that you want to set a timeout for all test methods in a given class, an easy way to do that is like this:

public class BlahTest {
    @Test(timeout = 1000)
    public void testA() throws Exception {
        // ...
    }

    @Test(timeout = 1000)
    public void testB() throws Exception {
        // ...
    }

    @Test(timeout = 1000)
    public void testC() throws Exception {
        // ...
    }

    @Test(timeout = 1000)
    public void testD() throws Exception {
        // ...
    }

    @Test(timeout = 1000)
    public void testE() throws Exception {
        // ...
    }

    // ...
}

Besides that you repeated yourself tons of times, if you want to change this timeout, you will have to change it in all methods. There is no need to do that. Just use the Timeout Rule:

public class BlahTest {
    @Rule
    public Timeout timeout = new Timeout(2000);

    @Test
    public void testA() throws Exception {
        // ...
    }

    @Test
    public void testB() throws Exception {
        // ...
    }

    @Test
    public void testC() throws Exception {
        // ...
    }

    @Test
    public void testD() throws Exception {
        // ...
    }

    @Test
    public void testE() throws Exception {
        // ...
    }

    // ...
}

Temporary Folder

Have you ever needed to do some test that uses File and/or needed a temporary file/folder? TemporaryFolder to the rescue:

public class BlahTest {
    @Rule
    public TemporaryFolder tempFolder = new TemporaryFolder();

    @Test
    public void testIcon() throws Exception {
        File icon = tempFolder.newFile("icon.png");
        // do something else...
    }
}

Expected Exceptions

Ever needed more control on exceptions? Try the ExpectedException rule:

public class BlahTest {
    @Rule
    public ExpectedException exception = ExpectedException.none();

    @Test
    public void testIcon() throws Exception {
        exception.expect(IllegalArgumentException.class);
        exception.expectMessage("Dude, this is invalid!");
        // do something that you expect to throw an exception...
    }
}

Custom Rules

That's neat, but... what if you need something else... something more "custom"? Well, you can implement your own rules by implementing the TestRule interface, for example, a Rule that init Mockito mocks (not very useful):

@RequiredArgsConstructor
public class MockRule implements TestRule {
  private final Object target;

  public Statement apply(Statement base, Description description) {
    return new Statement() {
      @Override
      public void evaluate() throws Throwable {
        MockitoAnnotations.initMocks(target);
        base.evaluate();
      }
    };
  }
}

To use it, you just need to declare that rule in your test class:

public class BlahTest {
    @Rule
    public MockRule mock = new MockRule(this);

    @Mock
    private BlahService service;

    @Test
    public void testBlah() throws Exception {
        Assert.assertThat(
            service.blah(),
            CoreMatchers.notNullValue()
        );
    }
}

External Resources

Returning to the example of this post's first paragraph, you can also have custom external resources rules by extending the ExternalResource class:

public class MyServer extends ExternalResource {
  @Override
  protected void before() throws Throwable {
    // start the server
  }

  @Override
  protected void after() {
    // stop the server
    }
}

I believe that this makes more sense with Integration Tests, though. Also, in this case, you probably would not want/need to start and stop the server before and after each test method, righ? So, you can use the @ClassRule annotation:

public class BlahServerTest {
    @ClassRule
    public static MyServer server = new MyServer();

    @Test
    public void testBlah() throws Exception {
        // test something that depends on the server.
    }
}

Attention: Note that when you use @ClassRule, your rule instance should be static, just like @BeforeClass and @AfterClass methods.

Going Further

That's the basics that will save you tons of abstract classes and ugly code. I would also recommend you to take a good read at the junit wiki. If you have any question, don't exitate to comment bellow, I will surely try to answer them. :beer:

Comment this post here.

Exponential Backoff with Java 8

Exponential backoff is an algorithm that uses feedback to multiplicatively decrease the rate of some process, in order to gradually find an acceptable rate. - Wikipedia

I recently used this strategy in work to deal with another service that we need to integrate. Sometimes, the service will just refuse the connection, without any reason. If I keep pushing, it will, someday, accept it.

So, I used Java 8 Functional Interfaces to implement this in a not-so-ugly way, also using a Fibonacci's Sequence to incremente the wait time:

The ExponentialBackOffFunction Functional Interface:

import java.rmi.RemoteException;

@FunctionalInterface
public interface ExponentialBackOffFunction<T> {
    T execute();
}

The ExponentialBackOff main class:

import static java.util.Arrays.asList;

import java.net.SocketTimeoutException;
import java.util.List;

import javax.net.ssl.SSLHandshakeException;

import lombok.extern.log4j.Log4j;

@Log4j
public final class ExponentialBackOff {
    private static final int[] FIBONACCI = new int[] { 1, 1, 2, 3, 5, 8, 13 };
    private static final List<Class<? extends Exception>> EXPECTED_COMMUNICATION_ERRORS = asList(
            SSLHandshakeException.class, SocketTimeoutException.class );

    private ExponentialBackOff() {

    }

    public static <T> T execute(ExponentialBackOffFunction<T> fn) {
    for (int attempt = 0; attempt < FIBONACCI.length; attempt++) {
            try {
                return fn.execute();
            } catch (Exception e) {
                handleFailure( attempt, e );
            }
        }
        throw new RuntimeException( "Failed to communicate." );
    }

    private static void handleFailure(int attempt, RemoteException e) {
        if (e.getCause() != null && !EXPECTED_COMMUNICATION_ERRORS.contains( e.getCause().getClass() ))
            throw new RuntimeException( e );
        doWait( attempt );
    }

    private static void doWait(int attempt) {
        try {
            Thread.sleep( FIBONACCI[attempt] * 1000 );
        } catch (InterruptedException e) {
            throw new RuntimeException( e );
        }
    }
}

Usage:

ExponentialBackOff.execute( () -> work() );

This will try to execute the work method incrementing the time between each call that fail with an expected error.

Comment this post here.

Elections, in Ruby

Updated with second round script in Oct 26, 2014.

Well, last sunday (Oct 5) was the brazilian elections. I was doing nothing, so I decided to write a simple ruby script to parse the results and show the top 3 candidates.

Besides the reverse clean-code done by the TSE (Superior Electoral Court), it was pretty easy:

Maybe the only interesting thing here is the metaprogramming in the String class.

Comment this post here.

Install JDK on OSX Yosemite

jdk

For some reason, Oracle blocked the installers to run only on a fixed OSX version range with a nice and explanatory error message. This range doesn't include Yosemite, which makes sense, since nobody running Yosemite will ever want to write some Java. Anyway, here is how to fix it.

First, download and open the JDK .dmg file. Then, unpackage and edit the Distribution file:

$ pkgutil --expand "/Volumes/JDK 7 Update 67/JDK 7 Update 67.pkg" /tmp/jdk7.unpkg
$ cd /tmp/jdk7.unpkg
$ vim Distribution

PS: I'm using vim, but you can use whatever editor you want, since it is vim.

Replace this function:

function pm_install_check() {
  if(!(checkForMacOSX('10.7.3') == true)) {
    my.result.title = 'OS X Lion required';
    my.result.message = 'This Installer is supported only on OS X 10.7.3 or Later.';
    my.result.type = 'Fatal';
    return false;
  }
  return true;
}

with this:

function pm_install_check() {
  return true;
}

just remove that if statement.

Then, just package and run the installer with:

$ pkgutil --flatten /tmp/jdk7.unpkg /tmp/jdk7.pkg
$ open /tmp/jdk7.pkg

The JDKs will be installed in the /Library/Java/JavaVirtualMachines/ folder.

You can also clean up your mess:

$ rm -rf /tmp/jdk7.*pkg

You can use this tip for JDK 8 too.

Comment this post here.

Java 8

Earlier this year, the new version of the Java Programming Language was released. Finally, it enters in the field of the "cool guys" with some features it should have since some years ago, like Lambdas.

"Java developers are now Hipsters again!"

Seen somewhere in the wild internet.

Anyways, I have been reading about and building simple algorithms with it since day one, but, now that I'm using it in a "real world" project, I would like to say some words about how the experience is going.

But firsts things first. The new features!

The new features!

Well, this version surelly have a lot of cool new features, so, I would like to point out my personal favorites!

1. Lambda Expression

This is really awesome. A lot of languages have this feature for years now, and for years I've been talking about how Java should have this. Now, finally, we have:

Runnable runnable = () -> System.out.println("Run forrest, run!");

Even if the implementation "behind the scenes" is not quite the best, in my humble opinion it is better than the interfaces with all that weird inner classes that we were using before:

Runnable runnable = new Runnable() {
  @Override
  public void run() {
    System.out.println("Run forrest, run!");
  }
};

2. The Stream collection types

I have to admit, this is awesome! We can do all sort of things with a DSL that is actually enjoyable to use:

Map<String, String> hash = new HashMap<>();
hash.entrySet().stream()
    .map(entry -> entry.getValue())
    .filter(entry -> entry.startsWith("C"))
    .distinct()
    .count();

There is also methods for parallel sorting and other stuff (parallelStream). Check also the IntStream class.

3. The new Date and Time API

This is another one that was required for years. Basically, they moved the Date/Time API to the java.time package and followed the Joda Time format, with the good thing that most classes are Threadsafe and immutable.

I just can't wait for Java 8 and the Money API! :moneybag:

4. String.join

I still can't believe that it taked so long...

System.out.println(String.join(". ", "FINALLY", "String", "joining"));
// FINALLY. String. joining

5. Optional

I posted about this in my Facebook timeline and it ends up becoming a little noisy. Anyway, I would really preffer a ruby-ish approach to this problem, but, well, this is better than nothing. I have used it in some filter calls like this, for example:

List<String> names = new ArrayList<>();
names.stream()
    .filter(entry -> entry.startsWith("C"))
    .findFirst() // returns an optional
    .get(); // tries to get its value (might throw NoSuchElementException)

Working with it in the wild

Update all the things! That's it.

I have to admit that I was expecting for this. Almost every library I was using before (with Java 6 or 7) had to be updated.

Some of them aren't even working, and needed some special attention, like openning a pull-request with the fixes and the deploy of custom version with the fix in local nexus repository until the new official version is released, but, nothing that can't be fixed.

This isn't really bad, it's just labor intensive... and a little tedious. Looking for the bright side, you always learn a little. :sparkles:

Resources

Well, you have probably read something about Java 8 already, but, if you didn't, or just want to read more, I recommend you to read the Java 8 Friday at the jOOQ's blog. They have plenty of good study material about this manner.

I could also recommend you a book that I have read: Java 8 Lambdas: Pragmatic Functional Programming. ?

If you want to read some Java 8 code, I have solved some katas using it just for fun. They are probably pretty bad, so feel free to suggest improvements. You can take a look at the source code here.

I have also ran a small Ruby Sinatra service with the last version of jRuby under JDK8 and it worked gracefully. You can take a look at it here.

Well, this is all for now. Feel free to ask anything you want in the comments box bellow!

Cheers!

Comment this post here.