Scheduled for release in 2013, Java 8 will include language support for lambda functions. Although the specification is still in flux, lambdas are already implemented in JDK 8 binaries.

This article takes a tour of the new lambda syntax, the use of lambdas in the Collections API, and related language enhancements. All code snippets were compiled with JDK 8 lambda build b39.

Functional interfaces

Interfaces that have just one method are called functional interfaces. Lambda expressions can be used anywhere we have a functional interface.

java.awt.event.ActionListener is a functional interface since it has one method, void actionPerformed(ActionEvent). In Java 7 we can write

button.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
        ui.dazzle(e.getModifiers());
    }
});
In Java 8 this becomes
button.addActionListener(e -> { ui.dazzle(e.getModifiers()); });

Here, the compiler knows that the lambda expression must conform to the signature void actionPerformed(ActionEvent). It sees that the lambda body returns void, and it can infer that type of parameter e is java.awt.event.ActionEvent.

Functional collections

The Java 8 class library has a new package, java.util.functions, which contains several new functional interfaces. Many of these can be used with the Collections API.

java.util.functions.Predicate

Use a predicate to filter a collection:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
List<String> filteredNames = names
        .filter(e -> e.length() >= 4)
        .into(new ArrayList<String>());
for (String name : filteredNames) {
    System.out.println(name);
}
Here we have two new methods:
  • Iterable<T> filter(Predicate<? super T>) which retains only those elements for which the predicate holds true
  • <A extends Fillable<? super T>> A into(A) which fills the ArrayList with all the elements retained after filtering

java.util.functions.Block

We can also replace the for loop with another new Iterable method, void forEach(Block<? super T>):

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
names
   .filter(e -> e.length() >= 4)
   .forEach(e -> { System.out.println(e); });
The forEach() method is an example of internal iteration: iteration happens inside the Iterable and our Block can see only one element at a time.

Finally, a less trivial example of functional programming with the Collections API:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
names
   .mapped(e -> { return e.length(); })
   .asIterable() // returns an Iterable of BiValue elements
                 // an element's key is the person's name, its value is the string length
   .filter(e -> e.getValue() >= 4)
   .sorted((a, b) -> a.getValue() - b.getValue())
   .forEach(e -> { System.out.println(e.getKey() + '\t' + e.getValue()); });

Programming collections in this style has some advantages:

Elements may be computed lazily
If we apply a Mapper to a collection of a thousand elements but only iterate over the first three, the remaining elements will never be mapped.
Method chaining is encouraged
Hence there's no need to store intermediate results in their own collections.
Internal iteration hides implementation decisions
For example, we could parallelize a map() operation just by writing myCollection.parallel().map(e ‑> e.length()).

Method references

We can reference a method using the :: syntax. Method references are treated the same way as lambda expressions and can be used wherever a functional interface is accepted.

We can reference a static method:
executorService.submit(MethodReference::sayHello);

private static void sayHello() {
        System.out.println("hello");
}
Or an instance method:
Arrays.asList("Alice", "Bob", "Charlie", "Dave").forEach(System.out::println);
We can also create factories by assigning a constructor reference to java.util.functions.Factory:
Factory<Biscuit> biscuitFactory = Biscuit::new;
Biscuit biscuit = biscuitFactory.make();

Lastly, let's create a reference to a method of an arbitrary instance:

interface Accessor<BEAN, PROPERTY> {
        PROPERTY access(BEAN bean);
}

public static void main(String[] args) {
        Address address = new Address("29 Acacia Road", "Tunbridge Wells");
        Accessor<Address, String> accessor = Address::getCity;
        System.out.println(accessor.access(address));
}
Here we do not need to bind the method reference to an instance. Instead, we pass the instance (in this case, address) as the first argument to the functional interface.

Default methods

With Java today, it is not possible to add methods to a published interface without breaking existing implementations. Java 8 gives us a way to specify a default implementation in the interface itself:

interface Queue {
        Message read();
        void delete(Message message);
        void deleteAll() default {
                Message message;
                while ((message = read()) != null) {
                        delete(message);
                }
        }
}
Subinterfaces can override a default method:
interface BatchQueue extends Queue {
        void setBatchSize(int batchSize);
        void deleteAll() default {
                setBatchSize(100);
                Queue.super.deleteAll();
        }
}
Or a subinterface can remove the default by redeclaring the method without a body:
interface FastQueue extends Queue {
        void deleteAll();
}
Doing this forces an implementation of FastQueue to implement deleteAll().

HotSpot implementation

Not only do lambda expressions give rise to more compact source code, but their bytecode and runtime implementation can be more efficient than the anonymous classes we would see in Java 7. For each lambda expression it finds, the compiler creates a method such as lambda$1(). This process is called lambda body desugaring. When the lambda expression is captured, the compiler emits an invokedynamic call site. This call site is responsible for capturing values from the lexical scope and binding the desugared method to the target functional interface.

Further reading

Much of this post is based on Brian Goetz's articles State of the Lambda, State of the Lambda: Libraries Edition and Translation of Lambda Expressions. Between them, these articles address the details of lambda syntax, variable capture, type inference and compilation.

13

View comments

  1. Ubuntu 14.04 does not have packages for NetCDF-Python or the Matplotlib Basemap Toolkit for Python 3. However, both can be installed from source without too much difficulty.
    1. Install the prerequisite packages with
      sudo apt-get install python3-matplotlib python3-dev libnetcdf-dev libgeos-dev libhdf5-dev
    2. Download and extract NetCDF-Python and install it with
      sudo python3 setup.py install
    3. Download and extract Matplotlib Basemap Toolkit
    4. If you try and install it, you will see the error
      /usr/bin/ld: cannot find -lgeos
      To avoid this, symlink the libgeos shared object
      sudo ln -s /usr/lib/libgeos-3.4.2.so /usr/lib/libgeos.so
      Then install as before using
      sudo python3 setup.py install
    To check the installation, try import both libraries at the Python 3 prompt:
    from netCDF4 import Dataset
    from mpl_toolkits.basemap import Basemap
    0

    Add a comment

  2. Having purchased a refurbished ThinkPad X301 this month, I set about installing Xubuntu 13.04. So far, the only problem I have had was with the Intel video drivers. I was seeing some screen corruption, especially with rxvt:

    Example of screen corruption with urxvt

    FreeDesktop's bug tracker confirmed that I wasn't alone in having the problem, and this post explains how I fixed it.
    aptitude purge xserver-xorg-video-all
    This is a metapackage that depends upon video drivers for all supported chipsets. You can safely uninstall it without uninstalling all the chipset drivers.
    Download the latest driver source
    Fetch the xf86-video-intel archive from the XOrg archives; as of August 2013, the latest version is 2.21.15.
    Install a toolchain
    If you don't already have them, you will need to aptitude install build-essential xserver-xorg-dev
    ./configure && make && make install
    Installs the Intel video driver into /usr/local. However, X11 does not scan this path by default1.
    aptitude purge xserver-xorg-video-intel
    Removes the older, packaged version of the driver
    ln -s /usr/local/lib/xorg/modules/drivers/intel_drv.so /usr/lib/xorg/modules/drivers/
    Symlinks the driver into a path where X11 can discover it
    Restart X11
    Drop to a tty with ctrl-alt-f1 and service lightdm restart

    1If anyone knows how to persuade X11 to search /usr/local/lib/xorg, tell me how in the comments.

    The screen corruption bug should be fixed in Ubuntu 13.10 since it will include a more recent driver version.
    0

    Add a comment

  3. Spring framework comes with a module, Spring Testing, that integrates with JUnit 4. It allows us to test Spring beans by wiring them into a JUnit test class. If we are writing an integration test, we may want to mock the dependencies of the bean under test. This article shows how to include those mock objects in a Spring ApplicationContext.

    As an alternative to XML configuration or classpath scanning, Spring recently added support for Java-based configuration. We'll take this approach in our example application.

    MyCollaboratorConfig.java

    @Configuration public class MyCollaboratorConfig {
        @Bean public MyCollaborator myCollaborator() {
            return new MyRealCollaborator();
        }
    }

    MyServiceConfig.java

    @Configuration @Import(MyCollaboratorConfig.class)
    public class MyServiceConfig {
        @Autowired private MyCollaboratorConfig collaboratorConfig;
     
        @Bean public MyService myService() {
            return new MyRealService(collaboratorConfig.myCollaborator());
        }
    }

    MyServiceTest.java

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes={MyServiceConfig.class, MyServiceTest.Config.class})
    @DirtiesContext(classMode=AFTER_EACH_TEST_METHOD)
    public class MyServiceTest {
        @Configuration public static class Config {
            @Bean public JUnitRuleMockery context() {
                return new JUnitRuleMockery();
            }
    
            @Bean public MyCollaborator myCollaborator() {
                return context().mock(MyCollaborator.class);
            }
        }
    
        @Rule @Autowired public JUnitRuleMockery context;
        @Autowired private MyService service;
        @Autowired private MyCollaborator collaborator;
    
        @Test public void doublesCollaboratorValue() {
            context.checking(new Expectations() {{
                allowing(collaborator).compute(); will(returnValue(42));
            }});
    
            assertThat(service.performUsefulFunction(), equalTo(84));
        }
    }

    Let's step through the test:
    @RunWith(SpringJUnit4ClassRunner.class)
    This JUnit 4 annotation lets Spring Testing hook into the testing lifecycle.
    @ContextConfiguration(classes={MyServiceConfig.class, MyServiceTest.Config.class})
    Instructs Spring to create an ApplicationContext containing beans loaded from two configuration classes: MyServiceConfig and MyServiceTest.Config. The order in which these classes are declared is important: a bean definition from MyServiceTest.Config will overwrite a bean definition MyServiceConfig if they share the same bean name.
    @DirtiesContext(classMode=AFTER_EACH_TEST_METHOD)
    Causes Spring to create a new ApplicationContext for each test method. Since mockeries are stateful, we need to dirty the ApplicationContext to ensure that we have a fresh Mockery for each test method.
    @Configuration public static class Config
    In this configuration class we define our mockery and any collaborators that we want to mock.
    @Bean public MyCollaborator myCollaborator()
    This bean definition shares the same bean name as MyCollaboratorConfig.myCollaborator(). When the test runs, you will see a message similar to this, confirming that our mock collaborator replaces the production collaborator:
    INFO: Overriding bean definition for bean 'myCollaborator':
    replacing
      [Root bean:
        factoryBeanName=myCollaboratorConfig;
        factoryMethodName=myCollaborator;
        defined in uk.co.datumedge.springmock.MyCollaboratorConfig]
    with
      [Root bean:
        factoryBeanName=myServiceTest.Config;
        factoryMethodName=myCollaborator;
        defined in uk.co.datumedge.springmock.test.MyServiceTest$Config]
    @Rule @Autowired public JUnitRuleMockery context
    Spring autowires the mockery bean defined in MyServiceTest.Config. The @Rule annotation is similar to @RunWith, allowing JMock to hook into JUnit's testing lifecycle.
    Now we can autowire the class under test, MyService, and its mocked collaborator. The remainder of the test class is written in the same style as a normal unit test.

    Spring Java configuration gotchas

    In Spring's Java-based configuration, @Configuration-annotated classes are themselves Spring beans. This allows us to wire them into other configuration classes and invoke their methods to wire beans together:
    @Configuration
    @Import(MyCollaboratorConfig.class)
    public class MyServiceConfig {
        @Autowired private MyCollaboratorConfig collaboratorConfig;
    
        @Bean public MyService myService() {
            return new MyRealService(collaboratorConfig.myCollaborator());
        }
    }

    How is it that our test uses the mock collaborator, when we can see our production collaborator being wired in this configuration class? To explain, we need to understand some of the pixie dust that Spring sprinkles over our source:
    • When a class is annotated with @Configuration, Spring generates a dynamic proxy class containing the mechanics needed to create bean definitions
    • When you invoke a method on a configuration class, you are really invoking a method on the generated proxy class

    Invoking a @Bean-annotated method will return a bean that matches the method's return type and method name. This is usually the instance returned by the method in the source code, unless that bean definition has been overridden.

    In our example application, MyServiceTest.Config.myCollaborator() has overridden MyCollaboratorConfig.myCollaborator(). Calling either method will return the same, mock object.

    Resources

    0

    Add a comment

  4. To test code that interacts with a REST resource, we need an HTTP server which provides access to a fake version of that resource. After a friend of mine released a fake HTTP library, I started thinking about whether JMock could be used to mock out REST resources.

    Let's work through an example application. We are writing a blog aggregator that has a single capability: to provide the most recent article from each blog in a collection blogs. The blogs are available as REST resources hosted on different HTTP servers.

    JMock

    JMock is a library that is normally used for mocking dependencies in unit tests. A unit test for our blog aggregator might look like this:

    public class BlogAggregatorUnitTest {
        @Rule public final JUnitRuleMockery context = new JUnitRuleMockery();
        private final BlogResource alicesBlogResource = context.mock(BlogResource.class, "Alice's Blog");
        private final BlogResource bobsBlogResource = context.mock(BlogResource.class, "Bob's Blog");
     
        @Test public void providesFeedContainingMostRecentArticleFromEachBlog() {
            context.checking(new Expectations() {{
                allowing(alicesBlogResource).get(); will(returnValue(alicesBlog));
                allowing(bobsBlogResource).get(); will(returnValue(bobsBlog));
            }});
     
            BlogAggregator aggregator = new BlogAggregator(ImmutableList.of(
                    alicesBlogResource,
                    bobsBlogResource));
            Feed feed = aggregator.aggregate();
            assertThat(feed, containsInAnyOrder(alicesMostRecentArticle, bobsMostRecentArticle));
        }
    }

    Jersey

    Jersey, the reference implementation of JAX-RS, exposes annotated POJOs as REST resources. Our blog resource looks like this:

    @Path("/")
    public interface BlogResource {
        @GET @Produces(APPLICATION_JSON) Blog get();
    }
    The library comes with a test framework that lets us serve resources from an HTTP server embedded in a JUnit test.

    Writing the integration test

    Our integration test is going to:

    1. Set up the test fixture by hosting two blog resources on local HTTP servers listening on different ports
    2. Use the Jersey client to HTTP GET and deserialize the JSON representation of the blogs
    3. Verify that the aggregator produces the expected feed

    Let's take a look at the test implementation:

    public class BlogAggregatorIntegrationTest {
        @Rule public JUnitRuleMockery context = new JUnitRuleMockery() {{
            setThreadingPolicy(new Synchroniser());
        }};
        private final BlogResource alicesBlogResource = context.mock(BlogResource.class, "Alice's Blog");
        private final BlogResource bobsBlogResource = context.mock(BlogResource.class, "Bob's Blog");
     
        private final JerseyTest alicesServer = aJerseyTest().withPort(9998)
                .addResource(alicesBlogResource).build();
     
        private final JerseyTest bobsServer = aJerseyTest().withPort(9999)
                .addResource(bobsBlogResource).build();
    
        @Before public void start() throws Exception {
            alicesServer.setUp();
            bobsServer.setUp();
        }
     
        @After public void stop() throws Exception {
            alicesServer.tearDown();
            bobsServer.tearDown();
        }
     
        @Test public void providesFeedContainingMostRecentArticleFromEachBlog() {
            context.checking(new Expectations() {{
                allowing(alicesBlogResource).get(); will(returnValue(alicesBlog));
                allowing(bobsBlogResource).get(); will(returnValue(bobsBlog));
            }});
      
            BlogAggregator aggregator = new BlogAggregator(ImmutableList.of(
                    clientFor(alicesServer),
                    clientFor(bobsServer)));
      
            Feed feed = aggregator.aggregate();
            assertThat(feed, containsInAnyOrder(
                    samePropertyValuesAs(alicesMostRecentArticle),
                    samePropertyValuesAs(bobsMostRecentArticle)));
        }
    
        private BlogResource clientFor(JerseyTest server) {
            return new RemoteBlogResource(server.resource().path("/"));
        }
    }

    A working version of the blog aggregator is available on GitHub.

    0

    Add a comment

  5. Scheduled for release in 2013, Java 8 will include language support for lambda functions. Although the specification is still in flux, lambdas are already implemented in JDK 8 binaries.

    This article takes a tour of the new lambda syntax, the use of lambdas in the Collections API, and related language enhancements. All code snippets were compiled with JDK 8 lambda build b39.

    Functional interfaces

    Interfaces that have just one method are called functional interfaces. Lambda expressions can be used anywhere we have a functional interface.

    java.awt.event.ActionListener is a functional interface since it has one method, void actionPerformed(ActionEvent). In Java 7 we can write

    button.addActionListener(new ActionListener() { 
        public void actionPerformed(ActionEvent e) { 
            ui.dazzle(e.getModifiers());
        }
    });
    In Java 8 this becomes
    button.addActionListener(e -> { ui.dazzle(e.getModifiers()); });

    Here, the compiler knows that the lambda expression must conform to the signature void actionPerformed(ActionEvent). It sees that the lambda body returns void, and it can infer that type of parameter e is java.awt.event.ActionEvent.

    Functional collections

    The Java 8 class library has a new package, java.util.functions, which contains several new functional interfaces. Many of these can be used with the Collections API.

    java.util.functions.Predicate

    Use a predicate to filter a collection:

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
    List<String> filteredNames = names
            .filter(e -> e.length() >= 4)
            .into(new ArrayList<String>());
    for (String name : filteredNames) {
        System.out.println(name);
    }
    Here we have two new methods:
    • Iterable<T> filter(Predicate<? super T>) which retains only those elements for which the predicate holds true
    • <A extends Fillable<? super T>> A into(A) which fills the ArrayList with all the elements retained after filtering

    java.util.functions.Block

    We can also replace the for loop with another new Iterable method, void forEach(Block<? super T>):

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
    names
       .filter(e -> e.length() >= 4)
       .forEach(e -> { System.out.println(e); });
    The forEach() method is an example of internal iteration: iteration happens inside the Iterable and our Block can see only one element at a time.

    Finally, a less trivial example of functional programming with the Collections API:

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
    names
       .mapped(e -> { return e.length(); })
       .asIterable() // returns an Iterable of BiValue elements
                     // an element's key is the person's name, its value is the string length
       .filter(e -> e.getValue() >= 4)
       .sorted((a, b) -> a.getValue() - b.getValue())
       .forEach(e -> { System.out.println(e.getKey() + '\t' + e.getValue()); });

    Programming collections in this style has some advantages:

    Elements may be computed lazily
    If we apply a Mapper to a collection of a thousand elements but only iterate over the first three, the remaining elements will never be mapped.
    Method chaining is encouraged
    Hence there's no need to store intermediate results in their own collections.
    Internal iteration hides implementation decisions
    For example, we could parallelize a map() operation just by writing myCollection.parallel().map(e ‑> e.length()).

    Method references

    We can reference a method using the :: syntax. Method references are treated the same way as lambda expressions and can be used wherever a functional interface is accepted.

    We can reference a static method:
    executorService.submit(MethodReference::sayHello);
    
    private static void sayHello() {
            System.out.println("hello");
    }
    Or an instance method:
    Arrays.asList("Alice", "Bob", "Charlie", "Dave").forEach(System.out::println);
    We can also create factories by assigning a constructor reference to java.util.functions.Factory:
    Factory<Biscuit> biscuitFactory = Biscuit::new;
    Biscuit biscuit = biscuitFactory.make();

    Lastly, let's create a reference to a method of an arbitrary instance:

    interface Accessor<BEAN, PROPERTY> {
            PROPERTY access(BEAN bean);
    }
    
    public static void main(String[] args) {
            Address address = new Address("29 Acacia Road", "Tunbridge Wells");
            Accessor<Address, String> accessor = Address::getCity;
            System.out.println(accessor.access(address));
    }
    Here we do not need to bind the method reference to an instance. Instead, we pass the instance (in this case, address) as the first argument to the functional interface.

    Default methods

    With Java today, it is not possible to add methods to a published interface without breaking existing implementations. Java 8 gives us a way to specify a default implementation in the interface itself:

    interface Queue {
            Message read();
            void delete(Message message);
            void deleteAll() default {
                    Message message;
                    while ((message = read()) != null) {
                            delete(message);
                    }
            }
    }
    Subinterfaces can override a default method:
    interface BatchQueue extends Queue {
            void setBatchSize(int batchSize);
            void deleteAll() default {
                    setBatchSize(100);
                    Queue.super.deleteAll();
            }
    }
    Or a subinterface can remove the default by redeclaring the method without a body:
    interface FastQueue extends Queue {
            void deleteAll();
    }
    Doing this forces an implementation of FastQueue to implement deleteAll().

    HotSpot implementation

    Not only do lambda expressions give rise to more compact source code, but their bytecode and runtime implementation can be more efficient than the anonymous classes we would see in Java 7. For each lambda expression it finds, the compiler creates a method such as lambda$1(). This process is called lambda body desugaring. When the lambda expression is captured, the compiler emits an invokedynamic call site. This call site is responsible for capturing values from the lexical scope and binding the desugared method to the target functional interface.

    Further reading

    Much of this post is based on Brian Goetz's articles State of the Lambda, State of the Lambda: Libraries Edition and Translation of Lambda Expressions. Between them, these articles address the details of lambda syntax, variable capture, type inference and compilation.

    13

    View comments

  6. Unless your project is hosted by an approved foundation such as Apache or Codehaus, you won't be able publish artifacts to Maven Central directly. Instead, Sonatype provide their own Nexus repositories for open source projects, and synchronise these with Maven Central.

    In this post I've tried to condense Sonatype's instructions, and include snippets from the POM file of my project, redis-launcher.

    Getting set up

    1. Add source code management information to your POM:
    2. Create a GPG key pair and publish the public key. See the Sonatype documentation for instructions.
    3. Check that your project POM meets the requirements for syncing
    4. Create a Sonatype JIRA account and raise a ticket to get your Nexus repository set up

    Using Maven to release to Sonatype Nexus repository

    1. Add the maven-release-plugin to your POM:
    2. Add the Sonatype repositories:
    3. Configure artifact signing:
    4. Edit or create ~/.m2/settings.xml to include your credentials: Maven does have a method to avoid storing plaintext passwords, but I have yet to try it.

    Cutting a release

    To cut a release, issue mvn clean release:prepare. Say your project is at version 0.1-SNAPSHOT. Preparing a release will remove the -SNAPSHOT suffix, commit and tag the code on github, then update the project version to 0.2-SNAPSHOT.

    If you need to undo the release, revert the changes with git reset --hard HEAD~2, and delete the tag with git tag -d redis-launcher-0.1 followed by git push origin :refs/tags/redis-launcher-0.1.

    Publishing to Sonatype

    1. If all is well, you can publish the project artifacts to Sonatype by issuing mvn release:perform
    2. Log into Sonatype Nexus and find your artifacts under Staging Repositories
    3. Close, then release the artifacts. Sonatype have some good instructions on using their web interface. You can automate these steps using the Maven repository management plugin, though I haven't tried it myself.
    4. Add a comment to your JIRA ticket to say that you've promoted the release
    The next time Sonatype synchronises (usually every few hours) your artifacts should be made available on Maven Central.
    6

    View comments

  7. Hamcrest is a useful library that lets you build assertions declaratively. Having worked with the library for a while now, I've found a few useful patterns and a handful of gotchas when writing Hamcrest matchers.

    Make matchers granular

    Sometimes you want to compare features of two objects having the same type. Instead of making one matcher that compares many features, write many matchers, each of which compares one feature. By doing this, you can use your custom matchers with Hamcrest's built-in combining matchers. FeatureMatchers work well for this type of fine-grained matcher. If the objects's features are bean properties you can avoid writing a custom matcher by using Hamcrest's hasProperty().

    Compose matchers

    You get more power by allowing matchers to accept other matchers. Here's an example that combines Hamcrest matchers to make an assertion on a JAX-RS Response:

    [Aside: Due to a bug in 1.3RC2, you will need to use a more recent version to get useful diagnostics from CombinableMatchers]

    Prefer TypeSafeDiagnosingMatchers over TypeSafeMatchers

    Unless your matchers are dealing with simple types such as Strings or primitives, TypeSafeDiagnosingMatchers will be able to produce better diagnostics. If you're seeing diagnostics such as Expected: status <404> but: was <com.sun.jersey.core.spi.factory.ResponseImpl@575b2f17>, you probably need a diagnosing matcher.

    Avoid null checks inside Matcher code

    TypeSafeMatcher and TypeSafeDiagnosingMatchers won't even call your matcher code if the actual value is null. If you're expecting a null value, use Matchers.nullValue() instead of a custom matcher.

    Avoid using mutable objects as actual or expected items

    Hamcrest assumes that Matcher.matches() is idempotent; indeed, TypeSafeDiagnosingMatcher.describeMismatch() gets called twice when two objects do not match. This means that you should avoid writing an InputStream matcher, for example.

    0

    Add a comment

Blog Archive
Tags
About Me
About Me
Loading
Dynamic Views theme. Powered by Blogger. Report Abuse.