Registries

Registries are lookup stores that allow specific values or implementations to be associated with a lookup key, typically a type of directory path, so that they can be looked up independently from different components or processes. Well-known examples include LDAP, the Windows Registry and Microsoft’s ActiveDirectory, Java’s JNDI with its various context interfaces like ServletContext and InitialContext, the Java RMI registry, and even runtime configuration files like those for Tomcat or Glassfish. To some extent even the venerable DNS and near-ubiquitous environment variables can be used as registries.

Registries usually allow their data to be organized hierarchically. Lookup stores like LDAP allow you to assign some degree of semantic meaning to levels of the hierarchy, such as the organizational unit (OU). Older registries only allowed the storage of values, originally as strings and later as typed data. In those systems, applications would use the values to construct resource locators. Newer systems also allow the storage of executable references, such as object and remote invocation references, so that the stored resource can be called directly without as much overhead.

The usefulness of registries comes from the ability to change them dynamically. When callable references are stored, you can replace a remote reference to a network-based service with a local object reference created by your test.10 If the values are used to generate a resource locator, you can substitute values that reference a resource under test control or at least one that is known to be appropriate for testing. Registries make useful seams because they provide an indirect form of dependency injection based on mutually known information: the lookup key.

10. This is a highly advisable strategy, not just to insulate your tests from use of the network but to protect your tests from interacting with each other both concurrently and sequentially.

Another way to use registries as seams is to simply replace the registry implementation. Depending on the context, some implementations make this easier than others. The key difference typically surfaces in how you bootstrap the registry. If a registry is a way to find global resources and a registry is a global resource, how do you find the registry? In environments in which the registry can be defined by configuration, such as J2EE containers, new registry implementations can be injected with ease, shown in Listings 12-13 and 12-14. Less flexible environments access the registry through static methods that are hardwired and cannot be overridden.

Listing 12-13: A basic servlet retrieving its ServletContext

public class MyServlet extends HttpServlet {
  public void service(HttpServletRequest request,
                      HttpServletResponse response)
      throws IOException, ServletException {
    ServletContext context = getServletContext();
  }
}

Listing 12-14: Using EasyMock to mock the ServletContext in a Java servlet. This approach safely intercepts calls into the registry representing the servlet’s context.

import static org.easymock.EasyMock.*;

public class MyServletTest {
  public void testService() throws Exception {
    ServletConfig servletConfig =
      createMock(ServletConfig.class);
    ServletContext servletContext =
      createMock(ServletContext.class);
    expect(servletConfig.getServletContext())
      .andReturn(servletContext).anyTimes();
    replay(servletContext, servletConfig);

    MyServlet sut = new MyServlet();
    sut.init(servletConfig);
    // Prepare a request and a response also
    ...
    sut.service(request, response);

    verify(servletContext, servletConfig);
  }
}

The same features that enable or prevent registry replacement are also liabilities when using registries as seams for testing. Even configurable registries are typically only configurable for an entire JVM or runtime environment. This introduces some of the same challenges of singletons in testing. At least in the context within which the registry is shared, there is the possibility that a misbehaving test could leave a substitute registry entry that would affect future test runs and that tests running concurrently could interfere with each other if they modified the same registry entries at the same time.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.67.5