Archive

Posts Tagged ‘unit test’
  • Improve your tests with Mockito's capture

    Unit Testing mandates to test the unit in isolation. In order to achieve that, the general consensus is to design our classes in a decoupled way using DI. In this paradigm, whether using a framework or not, whether using compile-time or runtime compilation, object instantiation is the responsibility of dedicated factories. In particular, this means the new keyword should be used only in those factories.

    Sometimes, however, having a dedicated factory just doesn’t fit. This is the case when injecting an narrow-scope instance into a wider scope instance. A use-case I stumbled upon recently concerns event bus, code like this one:

     public class Sample {
        private EventBus eventBus;
    
        public Sample(EventBus eventBus) {
            this.eventBus = eventBus;
        }
    
        public void done() {
            Result result = computeResult()
            eventBus.post(new DoneEvent(result));
        }
    
        private Result computeResult() {
            ...
        }
    }
    

    With a runtime DI framework - such as the Spring framework, and if the DoneEvent had no argument, this could be changed to a lookup method pattern.

    public void done() {
        eventBus.post(getDoneEvent());
    }
    
    public abstract DoneEvent getDoneEvent();
    

    Unfortunately, the argument just prevents us to use this nifty trick. And it cannot be done with runtime injection anyway. It doesn’t mean the done() method shouldn’t be tested, though. The problem is not only how to assert that when the method is called, a new DoneEvent is posted in the bus, but also check the wrapped result.

    Experienced software engineers probably know about the Mockito.any(Class<?>) method. This could be used like this:

    public void doneShouldPostDoneEvent() {
        EventBus eventBus = Mockito.mock(EventBus.class);
        Sample sample = new Sample(eventBus);
        sample.done();
        Mockito.verify(eventBus).post(Mockito.any(DoneEvent.class));
    }
    

    In this case, we make sure an event of the right kind has been posted to the queue, but we are not sure what the result was. And if the result cannot be asserted, the confidence in the code decreases. Mockito to the rescue. Mockito provides captures, that act like placeholders for parameters. The above code can be changed like this:

    {% highlight java linenos %} public void doneShouldPostDoneEventWithExpectedResult() { ArgumentCaptor captor = ArgumentCaptor.forClass(DoneEvent.class); EventBus eventBus = Mockito.mock(EventBus.class); Sample sample = new Sample(eventBus); sample.done(); Mockito.verify(eventBus).post(captor.capture()); DoneEvent event = captor.getCapture(); assertThat(event.getResult(), is(expectedResult)); } {% endhighlight %}

    At line 2, we create a new ArgumentCaptor. At line 6, We replace any() usage with captor.capture() and the trick is done. The result is then captured by Mockito and available through captor.getCapture() at line 7. The final line - using Hamcrest, makes sure the result is the expected one.

    Categories: Java Tags: testunit test
  • Speeding up your DBUnit tests with JavaDB

    Introduction to DBUnit

    DBUnit logoWith the developed use of JUnit, many additions were made to it. These additions take advantage of the pluggable nature of JUnit. One of these contribution is DBUnit. DBUnit enables your unit tests to:

    • preload the database with datas pertaining to your current test only,
    • run your unit test (as usual),
    • remove the data you preloaded in order to put the database in the same it was before your additions.

    In effect, you can now test your DAO classes. Let’s take a (very) simple example: a PersonDao class that manipulates Person objects.

    You create a test case that extends org.dbunit.JdbcBasedDBTestCase. It forces you to implement the following methods:

    • IDataSet getDataSet() throws Exception where IDataSet represents a collection of tables,
    • String getConnectionUrl() that returns the connection url of the database,
    • String getDriverClass() that returns the class name of the driver used for database access.

    This process enables you to test your DAO classes with various data sets. Moreover, these data sets can be initialized from various sources: I recently discovered one of these sources could be an Excel file ! Not very open-source, I agree, but very much more manageable than those cumbersome XML files.

    Yet, these tests are usually made on remote and shared databases. Drawbacks include:

    1. a sheer performance cost: remote databases use networks and, as such, increase the time to get the result, even if the databases themselves are very performant on their own,
    2. a risk of using the wrong datas: if using a shared database, you are taking chances that the data you want to use for your test has just been modified by another developer. If your DB uses a schema for each developer, well, that's just configuration overhead...

    The first point is a good way for developers not to write DB tests, since they can’t complete the build fast enough. The second point paves the road for correct tests to fail or more importantly, for incorrect tests to succeed. Both are bad.

    Using an alternate local DB

    The answer to these problems are the use of an alternate local DB. Yet, this solution has its own disadvantages including: license costs, configuration overhead for each developer’s machine and the ever-popular “It doesn’t work on my computer”. Well, let’s get back to the shared BD ? Clearly no: there’s a often overlloked option.

    Apache Derby logoSince version 6 of the JVM, Sun ships an embedded database with its JDK. This DB, called oh-so-originally JavaDB, is a reuse of the not-so-old Apache Derby database project. Apache Derby, is an open source relational database implemented entirely in Java.

    Main advantages are:

    • a small memory footprint,
    • the main SQL-99 Core / SQL-2003 mandatory features (see table for unsupported features),
    • an embedded driver.

    Quick how-to

    First of all, you should provide a mechanism to provide a connection in different ways, for example with dependency injection, probably the method you will choose for a real-world project (be it with Spring or Guice). For my proof-of-concept, I chose the method-overloading mechanism to keep it simple (KISS without the trailing S).

    Then, it’s all very simple:

    • the getConnectionUrl() should return "java:derby:[your_chosen_db_name];create=true",
    • the getDriverClass() should return "org.apache.derby.jdbc.EmbeddedDriver",
    • the getDataSet() should return very simply getConnection().createDataSet().

    Et voilà !

    The Maven artifact that contains an example is just here: JavaDB example sources

    Conclusion

    The use of JavaDB is not the golden hammer to your DB tests problems. According to me, there’s much to be done in order for it to be really full-SQL compliant. Yet, 90% of the common SQL requests used troughout prjects can be parsed by it. There’s even an Hibernate dialect available. In conclusion, it can save much anguish and much time for developers. So, why don’t use it ?

    Categories: Java Tags: dbunitderbyjavadbunit test
  • The unit test war : JUnit vs TestNG

    What is unit testing anyway?

    If you’re in contact with Java development, as a developer, an architect or a project manager, you can’t have heard of unit testing, as every quality method enforces its use. From Wikipedia:

    "Unit testing is a test (often automated) that validates that individual units of source code are working properly. A unit is the smallest testable part of an application. In procedural programming a unit may be an individual program, function, procedure, etc., while in object-oriented programming, the smallest unit is a method, which may belong to a base/super class, abstract class or derived/child class. Ideally, each test case is independent from the others."

    Unit tests have much added value, apart from validating the working of your classes. If you have to change classes that you didn’t develop yourself, you should be glad to have them… because if they fail, it would instantly alert you of a failure: you won’t discover the nasty NullPointerException you just coded in production!

    Before the coming of testing frameworks (more later), the usual testing was done:

    • either manually, eventually traced on an external document,
    • in the main method of the class.

    Both of the options were dead wrong. In the first case, it was impossible to know what test was passed, if the trace was up-to-date. In the second case, all your classes would become executable in the production environment, not a very good design.

    The coming of JUnit

    Then came Erich Gamma (yes, the same who wrote about design patterns!) and his magical framework JUnit. JUnit just industrializes your unit tests without messing with your code base proper. You just write a class in the right way and presto, you can launch JUnit to pass the tests. The test classes can be localized anywhere you please so you don’t have to ship them along with your application.

    Even better, now that JUnit has gained widespread recognition, every tool proposes to plug into it:

    • most IDEs (Eclipse, NetBeans, what have you) propose integrated plugins,
    • Ant provides a JUnit task that can run from your build,
    • Event better, if you put your tests in a specific Maven foldern, namely src/test/java, they are run automatically and if a test fails, it breaks the build.

    Cons

    Well, it can’t get better, can it? Yet, when using JUnit extensively, you can’t avoid to see some drawbacks.

    Parameters

    First of all, JUnit doesn’t allow for parameters. For example, let’s say that you want to test the following generic method:

    public <T extends Number> T add(T p1, T p2) {...}
    

    In the JUnit framework, you would have to implement at least two test methods, one for integers and one for decimal point numbers, and better, one for each Number type. The most rational use would be to code a single test method and to call it many times, each time passing a different set of parameters.

    Grouping

    JUnit test classes can be grouped into packages like any regular classes. But I would like to group my tests into a nicely organized hierarchy to know precisely where my tests are failing. For example:

    • a functional group,
    • a technical group
    • and a gui group.

    JUnit doesn’t provide an answer.

    Time cost of running tests

    Followers of Agile methodologies preach that builds, including unit tests, should be run in less than 10 minutes. I’m not sure if that’s the good limit, but I agree that a build should be the fastest possible.

    What about failed tests? In my opinion, if your build fails because of failed tests, it should be at the earliest time possible. What’s the point of running more tests if the build is fated to fail? That’s only a waste of time.

    More precisely, I want my framework not to run all my database tests if a test method informs me the database can’t be accessed whatever the reason. A nice feature would be to have natively such a dependency mechanism in the testing framework.

    Where do we go from here?

    I recently discovered another testing framework. The name is TestNG: the authors freely ackonwledge their framework is directly inspired from JUnit. It provides every functionality of JUnit and solves all the aforementioned problems.

    Morevover:

    • the Java 5 version of TestNG uses exactly the same annotation names as JUnit,
    • if you want to keep your JUnit tests, TestNG can run JUnit tests,
    • if you don't want, specific converter classes make the migration a breeze,
    • there are Eclipse and IDEA plugins available,
    • TestNG tests are run natively by Maven.

    In conclusion, I have nothing against JUnit, on the contrary. It did a marvelous job in making unit testing easy and we, as developers, owe their authors. But it is not a final product: it can be enhanced (see all the extensions people made). TestNG is such an enhancement, I can’t recommend enough its use.

    Categories: Java Tags: junittestngunit test