Tag Archives: jmockit

How to unit test Java servlets

The question of how to unit test Servlets comes up a lot. How can it be done? Should it be done? What are the options?

A unit test, in the realm of xUnit semantics, is an isolated test of the smallest testable subset of a program. Usually this translates to a test of a single method in an Object. When this object itself is part of a framework or container, such tests border on becoming Integration Tests. How could these types of objects still be ‘unit tested’?

Written by: Josef Betancourt, Date: 2015-09-17, Subject: Servlet testing

Options

Here are a few options.

POJO

When you write a servlet, ultimately the servlet object is instantiated by the server container. These objects do a lot behind the scenes that may prevent invoking methods on them when not attached to an actual container.

A servlet, or any other server based object like an EJB, provides access to problem domain services or functionality. The easiest way to test these Objects is to refactor that service into plain old Java objects, POJO.

Jakob Jenkov writes: “… push the main business logic in the servlet into a separate class which has no dependencies on the Servlet API’s, if possible”.

If your working with a framework that is likely the design approach anyway.

Servlet stub library

A library that allows creation of “server” objects can make creating stubs for testing very easy. Again, a framework should provide such a feature.

Mocking

Mocking using modern libraries like Mockito, Powermock, and JMockit, provides a very powerful approach. There is also what appears to be a more focused Mockrunner project, which has a mockrunner-servlet module.

In listing 1 below, a test is created for a target SutServlet class’s doGet. This method will set the response status to 404 if an ID request parameter is null.

Using JMockit, proxies of HttpServletRequest and HttpServletResponse are created. The request’s getParameter and the response’s setError methods are mocked. The actual unit test assertion is done in the mocked setError method.

Listing 1, JMockit use

@RunWith(JMockit.class)
public class SutServletTest_JMockit {
    
    @Test
    public void should_Set_ResourceNotFound_If_Id_Is_Null() throws Exception {
        new SutServlet().doGet(
        new MockUp<HttpServletRequest>() {
            @Mock
            public String getParameter(String id){
                return id.compareToIgnoreCase("id") == 0 ? null : "don't care";
            }
        }.getMockInstance(),
        new MockUp<HttpServletResponse>() {
            @Mock
            public void sendError(int num){
                Assert.assertThat(num, IsEqual.equalTo(HttpServletResponse.SC_NOT_FOUND));              
            }
        }.getMockInstance());
    }
     
}

JDK Dynamic Proxies

The Mock approach can also be duplicated using dynamic proxies. JDK dynamic proxy support is usable here. JDK proxies have one limitation, they can only proxy classes that extend an interface. (Still true in Java 9?). Servlets extend interfaces, so we can the proxy support in the JDK.

Listing 2, using JDK proxies

public class SutServletTest_using_jdk_proxy {
    
    private static final String DON_T_CARE = "don't care";
    private static final String SEND_ERROR = "sendError";
    private static final String GET_PARAMETER = "getParameter";

    /**  @throws Exception  */
    @Test
    public void should_Set_ResourceNotFound_If_Id_Is_Null() throws Exception {
        
        // request object that returns null for getParameter("id") method.
        HttpServletRequest request  = (HttpServletRequest)Proxy.newProxyInstance(this.getClass().getClassLoader(),
            new Class[]{HttpServletRequest.class},
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if(method.getName().compareToIgnoreCase(GET_PARAMETER) ==0){
                            return ((String)args[0]).compareToIgnoreCase("id") == 0 ? null : "oops";
                        }
                        return DON_T_CARE;
                    }
                }
        );
        
        // Response object that asserts that sendError arg is resource not found: 404.
        HttpServletResponse response  = (HttpServletResponse)Proxy.newProxyInstance(this.getClass().getClassLoader(),
            new Class[]{HttpServletResponse.class}, 
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if(method.getName().compareTo(SEND_ERROR) == 0){
                            Assert.assertThat((Integer) args[0], IsEqual.equalTo(HttpServletResponse.SC_NOT_FOUND));
                        }
                        return DON_T_CARE;              }
                }
        );
         
        new SutServlet().doGet(request,response);
    }
}

Javassist Proxies

Just for completeness, in listing 3, we use the Javassist library.

Listing 3, using Javassist proxy

public class SutServletTest_using_assist {
    
    private static final String DON_T_CARE = "don't care";
    private static final String SEND_ERROR = "sendError";
    private static final String GET_PARAMETER = "getParameter";

    /**  @throws Exception  */
    @Test
    public void should_Set_ResourceNotFound_If_Id_Is_Null() throws Exception {
        
        // request object that returns null for getParameter("id") method.
        HttpServletRequest request  = (HttpServletRequest)createObject(new Class[]{HttpServletRequest.class},
            new MethodHandler() {
                public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
                    if(thisMethod.getName().compareToIgnoreCase(GET_PARAMETER) == 0){
                        return ((String)args[0]).compareToIgnoreCase("id") == 0 ? null : "oops";
                    }
                    return DON_T_CARE;
                }
            }
        ); 
        
        // Response object that asserts that sendError arg is resource not found: 404.
        HttpServletResponse response  = (HttpServletResponse)createObject(new Class[]{HttpServletResponse.class},
            new MethodHandler() {
                public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
                    if(thisMethod.getName().compareTo(SEND_ERROR) == 0){
                        Assert.assertThat((Integer) args[0], IsEqual.equalTo(HttpServletResponse.SC_NOT_FOUND));
                    }
                    return DON_T_CARE;
                }
            }
        );
         
        new SutServlet().doGet(request,response);
    }
    
    /**
     * Create Object based on interface.
     * <p>
     * Just to remove duplicate code in should_Return_ResourceNotFound_If_Id_Is_Null test.
     * @param interfaces array of T interfaces
     * @param mh MethodHandler
     * @return Object
     * @throws Exception
     */
    private <T> Object createObject(T[] interfaces, MethodHandler mh ) throws Exception{
        ProxyFactory factory = new ProxyFactory();
        factory.setInterfaces((Class<?>[]) interfaces); // hmmm.        
        return factory.create(new Class[0], new Object[0], mh);
    }
}

Embedded server

Its also possible to start an embedded server, deploy the servlets, and then run the tests. Various Java app servers (like Tomcat and Jetty) support this and are well documented. The complexity comes when only partial integration is required. For example, we may want to have a real app server running the tests, but do we also really need a database server too? Thus, we also have to deploy stubs or mocks to this embedded server. Many resources on web for this approach, for example, “Integration Testing a Spring Boot Application“.

Another approach is the concept of the Hermetic Servers.

AOP

AOP can be used on embedded server, and this would allow “easy” mocking of integration endpoints and mocks. Such an approach was shown here “Unit test Struts applications with mock objects and AOP“.

References

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Unit testing Java exception handling using JMockIt

How do you test that a method caught an exception? What if that catch did not have a side effect, it just logged output, or simply swallowed the exception?

Context
We have a method in a class that was written with a try catch and we need to unit test it. There are many ways this task can occur, such as the need to test legacy code or the need to write a test before a refactoring of such code.

We won’t go into the anti-pattern aspects or what constitutes proper handling of an exception here.

Error hiding is an anti-pattern in computer programming. Due to the pervasive use of checked-exceptions in Java, we must always address what to do with exceptions. Error hiding is when a catch clause does not property handle an exception.
 

In a catch block there are three common ways of handling an exception:

try{
   ... stuff ...
}catch(X){
   // 1. do something here
   // 2. maybe throw X or something else
   // 3. skip the above and do nothing
}

How are these tested?

Thrown exception
When the method reacts by throwing an exception we can test using the standard JUnit @Test(expected=SomeException.class), or for fine-grained verification, the test itself has a try catch block where we can assert the exception details.

Swallowed exception
If a method does nothing in the catch block, which is also called “swallowing” the exception, should it even be a test issue? Yes. The method is just tested normally. One of the tests must force the exception, of course. We do this since in future the method may be changed to handle the exception differently. One of the test assertions that can be made is that the forced exception is not thrown from the method.

Exception handler pointcut
Testing that an exception in the method under test was actually caught is possible, but only with Aspect Oriented Programming (AOP). One example language is AspectJ which supports the pointcut:

handler(TypePattern)
Picks out each exception handler join point whose signature matches TypePattern.
 

Behavior in catch
It gets more interesting when the catch block has ‘behavior’. This behavior has side effects. If these side effects are only local to the method, such as setting a flag false, then normal testing is adequate. If this behavior has side effects at the class or with collaborating objects, then this requires more complex testing.

It can get murky with this kind of testing. What is important is that one does not test the implementation (but sometimes that is crucial), only the interactions and requirements of the target “Unit” under test. What constitutes a “unit” is very important.

“Typically, a unit of behavior is embodied in a single class, but it’s also fine to consider a whole set of strongly-related classes as a single unit for the purposes of unit testing (as is usually the case when we have a central public class with one or more helper classes, possibly package-private); in general, individual methods should not be regarded as separate units on their own.” — Rogerio in JMockit Tutorial

.

Example
The method being tested invokes a method on a collaborating object and that object throws an exception. In the catch block, the exception is logged using the logging utility collaborator . Though not part of an explicit API, that logging may be critical to the use of a system. For example, an enterprise log monitoring system expects this logging for support or security concerns. A simple class Shop is shown in figure 1,

Figure 1, the class to test

public class Shop {
    private ShoppingSvc svc;
    
    /**
     * Get product name.
     * @param id the unique product id
     * @return the product name
     */
    public String getProduct(int id){
        String name = "";
        try {
            name = svc.getProductName(id);
        } catch (Exception e) {
            Logger.getAnonymousLogger()
			.log(Level.SEVERE, 
			"{result:\"failure\",id:\""+ id + "\"}");
        }
        
        return name;
    }
    
}

JMockit Use
JMockit supports two type of testing: behavior and state-based (or “Faking”).
Using the state based approach we create a mock for the getProductName(String) method of the collaborating (or dependent) class, ShoppingSvc. With JMockit this is easily done as an inline MockUp object with the target method mocked to throw an exception.

Listing 2, mocking

new MockUp<ShoppingSvc>() {
    @Mock
    public String getProductName(int id) throws IOException{
		throw new IOException("Forced exception for testing");
    }
};

JMockit’s behavior based support is then used to test the catch clause handling. As in other mocking frameworks, a record-replay-verify phases are used. Since the side effect of the exception handler here is the use of the logging dependency and we are not testing the logger, we ‘behaviorally’ mock the Logger class.

We can do this in the test method signature, @Mocked final Logger mockLogger. This mocks every method in the logger class. Then we set an expectation on the log method being used in the exception handler, then verify the method was actually invoked.

The full test class is shown in figure 3 below and the sample code is in a repo on GitHub:https://github.com/josefbetancourt/examples-jmockit-exceptions.

An alternative to using both state and behavior mocking is to just specify the exception throwing with the expectations. The article “Mocking exception using JMockit” shows how to do this. Of course, the JMockit Tutorial has all the details.

Listing 3, the full test class

@RunWith(JMockit.class)
public class ShopTest{
    /**
     * 
     * @param mockLogger Logger object that will be behaviorally mocked.
     */
    @Test
    public void shouldLogAtLevelSevere(@Mocked final Logger mockLogger)
    {
        /**
         * state-based mock of collaborator ShoppingSvc
         */
        new MockUp<ShoppingSvc>() {
            @Mock
            public String getProductName(int id) throws IOException{
                throw new IOException("Forced exception for testing");
            }
            
        };
        
        // the SUT  
        final Shop shop = new Shop();

        // what we expect to be invoked
        new Expectations() {{
            mockLogger.log(Level.SEVERE,anyString); 
        }};
        
        shop.getProduct(123); // actual invocation
        
        // verify that we did invoke the expected method of collaborator
        new Verifications(){{
            mockLogger.log(Level.SEVERE, anyString);  // we logged at level SEVERE
        }};
    }
}

Alternatives?
Just write better code so that you don’t need unit tests? This is mentioned in Functional Tests over Unit Tests

Test using a scripting language like Groovy? See Short on Time? Switch to Groovy for Unit Testing

Software
– JUnit: 4.12
– JMockit: 1.18
– JDK: 1.8
– Eclipse: Mars
– Maven: 3

Links

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Mock Java time and date using JMockIt

Example scenario: A class under test (CUT) gets the current date and uses collaborating classes that invoke month dependent rules. How can it be unit tested?

Sure you can get the current date in the test and set the month. But, the CUT and all of its collaborators may also get the current date. Without changing the environment system time how will you force the month to be, for example, December?

That this is a problem may indicate there is a code smell in the design, but in a non test infected group, tests are added, if at all, after the code is shipped. Thus, changes are scheduled for the next agilefall.

One easy approach is to just change what Calendar.getInstance() gives you. With JMockIt this is very easy. Just put something like the anonymous mock (see lising 1) in the test method.

Source code

/** 
  * Test December rules.
  * @author J. Betancourt
  */
@Test
public void should_invoke_December_rules(){
    new MockUp<Calendar>() {
    	@Mock
    	public Calendar getInstance(Invocation inv) {
    		Calendar cal = inv.proceed();
    		cal.set(Calendar.MONTH, 11);
    		return cal;
    	}
    };

    doTestStuffHere();

}

Listing 1.

Note that within the mocked method I still have access to the mocked class instance cause I also included an Invocation as the first argument, thus I invoke that to get the calendar as usual, then I change the month. Kind of like an Aspect ‘around’ advice.

JMockIt performs instrumentation via java.lang.intrument and the ASM library, so even collaborating objects will use this Mocked instance for the life of the test. This is a big feature offered by JMockIt compared to other Mocking frameworks afaik.

This should be applicable to mocking other temporal methods like System.currentTimeMillis(), and that in itself effects other methods to get date and time.

Caution
Mocking JDK classes may have side effects on running tests. In one of my tests, the java.io.Printwriter was mocked. This caused Eclipse to disconnect from the running JUnit test. The solution was: right after executing the method that involved the use of the writer, doing a mock tearDown(). This was on a JMockIt version 1.2. It probably changed in the latest version.

Shouldn’t time be accessed from a testable configurable component?
Getting time related data via Calendar.getInstance(), System.currentTimeMillis(), or other JVM provided facilities is bad practice in some cases. It is similar to using “new “, creating hidden object graphs, and making testing difficult. A better approach is to centralize the time related access through a service or utility class. One benefit of this is that to change the environment date for a ‘system’ test, you don’t have to change the vacuum tubes in the mainframe system, just change the calendar access via configuration.

Notes
1. This worked on JDK 1.6 using JMockIt version 1.2. Is it a good technique? Let me know.
2. After I wrote this I searched for this topic and found many good blog posts discussing this subject. Why didn’t I find these when I initially had the problem?

Further reading

Something I’m listening to while I code …

“Become, Seem, Appear” performed by Oregon on their CD “Oregon In Concert”. On YouTube
Price for a new CD is $5,545.60. I better find my CD and store it in a safe place!

“The Silence Of A Candle” performed by Oregon on their CD “Oregon In Concert”. On YouTube.

Audio CD (November 6, 2001), Original Release Date: 1975, ASIN: B00005RDJS

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Use AOP Aspects as Mocks in JUnit tests?

This post illustrates a subtle relationship between Mock Objects and Aspect Oriented Programming. Some code examples are shown, and ends with questions for further research. This is a follow on to a prior “Using AspectJ For Testing Legacy Code“. Author: Josef Betancourt

Use AOP Aspects as Mocks in JUnit tests?

Written by:
Josef Betancourt
Date:
2013-05-29
Subject:
AOP vs Mocks for testing

Categories and Subject Descriptors
D.2.2 [Software Engineering]: Design Tools and Techniques, Object-Oriented programming

Keywords
interceptors, AOP, Mock Objects, JMockit, JUnit, Aspectj, unit test

Introduction
In Unit testing during code development and maintenance, the smallest unit of code is tested in isolation from collaborating units or subsystems. In well designed systems, testing is much simpler: outgoing interfaces are easier to manage. In legacy systems and/or badly written code, that may not be the case. Further, when testing legacy systems, changes to increase testability are not always possible.

Thus, various patterns, frameworks, and tools are used to support this isolation. Mock Object frameworks are ideal for this. Aspect Oriented Programming (AOP) is also capable of providing this isolation but is rarely mentioned. What are the differences? Is one better than another for testing?

Aspect Oriented Programming
See the wikipedia entry for more information.
In the Java world, AspectJ is the most well-known AOP implementation.

Mock Objects
Mock Objects are simulated objects that mimic the behavior of real objects in controlled ways.

The JMockit toolkit is a modern Java mocking toolkit. One distinguishing feature of JMockit is that it is powerful enough to Mock legacy unmockable code.

Example Project
A Client class uses a Service object’s query method to get a user’s name: Client.getUserName(int) –> Service.query(int).

For the test we want to substitute the name for a specific argument. When invoked with argument integer 1, the result is the string “second”, but in the test we want to return “Hello world!”. This example is just to show the technology; a hello world app, not practical in itself.

Advice.
To intercept a method call on an object in AOP an Aspect is created.

“Aspects wrap up pointcuts, advice, and inter-type declarations in a modular unit of crosscutting implementation.”
 

The Advice below is written in the annotation based AspectJ syntax introduced in AspectJ 5.

@Aspect
static class TestAspect {
		
	@Pointcut("call( * AspectJUnit.Service.query(int)) && args(i)")		
	void intercept(int i){}
		
	@Around("intercept(i)")
	public String query(ProceedingJoinPoint tjp, int i){
	    return (i == 1) ? "Hello world!"
		: (String) tjp.proceed(new Object[]{i});
	}		
	
}
 

This defines a method that will ‘replace’ the original target. The terminology used by the AspectJ programming manual:

• A Join Point is a well-defined point in the program flow.
• A Pointcut picks out certain join points and values at those points.
• An Advice is code that is executed at a join point.
 

AspectJ defines many Join Points. There is even a Handler execution join point: “When an exception handler executes. Handler execution join points are considered to have one argument, the exception being handled”.

The pointcut language is very rich and the signature patterns can be generic or very specific.

We can also use an anonymous pointcut instead:

@Aspect
static class TestAspect {
		
	@Around("call( * AspectJUnit.Service.query(int)) && args(i)")
	public String doQuery(ProceedingJoinPoint jp, int i){
	    return (i == 1) ? "Hello world!"
		: (String) jp.proceed(new Object[]{i});
	}		
	
}
 

Note that the advice, here doQuery(..), does not have to match the original target method’s name.

Mocking
In JMockit‘s State Based API an object can be mocked by using a MockUp class. Within that class any method that needs to be mocked is re-implemented and annotated with @Mock.

Since JMockit allows even private, final, or static methods to be overridden, this is not normal Java method overriding.

class MockService extends MockUp<Service> {
	@Mock
	public String query(Invocation invocation, int n) {
		return (n == 1) ? "Hello world!"
			: ((Service) invocation.
			getInvokedInstance()).query(n);
	}			
}
 

We can also define the mock using an anonymous inline class within the test method:

new MockUp<Service>() {				
        @Mock
	public String query(Invocation invocation, int n) {
	     return (n == 1) ? "Hello world!" 
              : ((Service) invocation. 
                getInvokedInstance()).query(n);
	}
};
 


Comparison
Structure and Syntax
Compare this to the prior Aspect. They are both a class definition. The new behavior is also a method. The difference is the pointcut. In JMockit the pointcut and the advice specification are combined. Note that the method signature must match the target method’s. In the AspectJ Aspect, these are separate.

@Aspect
static class TestAspect {
		
	@Around("call( * AspectJUnit.Service.query(int)) && args(i)")
	public String doQuery(ProceedingJoinPoint jp, int i){
	    return (i == 1) ? "Hello world!"
		: (String) jp.proceed(new Object[]{i});
	}		
	
}
class MockService extends MockUp<Service> {

	@Mock
	public String query(Invocation invocation, int n) {
		return (n == 1) ? "Hello world!"
			: ((Service) invocation.
			getInvokedInstance()).query(n);
	}			
}
 

The combined syntax in the Mock approach is simpler, and since a test is usually targeted at one specific method, the extra AOP pointcut expressiveness may have limited use. The Mock class can even be created in the test inline. A paper referenced below even makes the suggestion that test based pointcut definitions are an improvement to AOP since they are less fragile.

The aspect must be created as a static class and the associated advice is instrumented at compile time. The mock is integrated in the JUnit run time so it’s ‘advice’ is active only for the current test, thus, you have more opportunities for various tests of the same target. The full source code of the test using Aspects does not have as many assertions as the one written using Mocks because of this early instrumentation. See section below for listings.

There are more differences. These are of course due to the intended application of these two technologies. AOP is a more general purpose systems tool. Crosscutting concerns are an architectural artifact whereas isolation is a testing concern.

Mocks are a subset of Aspects
AOP is optimized for cross-cutting concerns. But, collaborator isolation is just an example of a single-use test-based cross-cutting concern. So Mocks are just a special use of general AOP capabilities.Mocks supply a single joinpoint, and in many implementations allow the use of an Around advice. This has been sufficient and with other features such as Expectations, the Mock Objects framework fits well into current testing approaches.

In AOP there is a richer language for selecting different kinds of joinpoints. And the pointcuts are used by different kinds of advice, such as cflow, before, after, around, and so forth. The modularization (inheritance and other features) into Aspects presents an opportunity for more high-level syntax and use, especially with the annotation based language.

Can Mock Objects use AOP techniques?
This begs the question of whether Mock Objects can or should use generic AOP techniques? If so how?

One example of the integration of AspectJ is the Spring framework, which now can use the AspectJ pointcut language in its own AOP implementation. Spring’s implementation is not specifically targeted as a test solution.

Another technology is the use of a language that can create “advice” rules and be invoked via instrumentation. This is available in Byteman. Byteman uses Event Condition Action (ECA) rules.

More recent versions of JMockit now supports a ‘wildcard’ mock method: ‘”Object $advice(Invocation)”, which if defined will match every method in the mocked class hierarchy.’ — mockit Annotation Type Mock

If AOP pointcuts do have a use-case in testing mocks, could this be an area where a pointcut DSL could be introduced in future?

 

Aspects and Mocks shown in full listings

Example Mocks in a JUnit test
package com.octodecillion.jmockit.example;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

import java.util.Arrays;
import java.util.List;

import mockit.Invocation;
import mockit.Mock;
import mockit.MockUp;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * mockit.Invocation class use example
 */
public class JMockItExample2 {

	/**  the client we are testing */
	public class Client {
		private Service service;
		
		public Client(Service service) {
			this.service = service;
		}
		
		/** invoke the 'expensive' service. */
		public String getUserName(int n){
			return service.query(n);			
		}
		
	}
	
	/** the service that does integration stuff */
	public class Service {
			/**
			 * @param key 
			 * @return 
			 */
			public String query(int n) {				
				return values.get(n);
			}
			
			private final List<String> values = 
				Arrays.asList("first","second","third");
	}
	
	/**
	 * Nested test class.
	 *
	 */
	@RunWith(JUnit4.class)
	public static class UnitTest{
		private JMockItExample2 example;
		
		@Before
		public void before(){
			example = new JMockItExample2();
		}
		
		/**   */
		@Test
		public void should_do_around_advice() {
			String expected = "second";
			String actual = example.new Service().query(1);
			assertThat(actual, is(expected));
			
			new MockUp<Service>() {				
				/**
				 * Use an Invocation to allow use of mocked object.
				 */
				@SuppressWarnings("unused")
				@Mock
				public String query(Invocation invocation, int n) {
					return (n == 1) ? "Hello world!"
						: ((Service) invocation.
						getInvokedInstance()).query(n);
				}
			};
			
			expected = "Hello world!";
			actual = example.new Service().query(1);
			assertThat(actual, is(expected));
			
			// do the around advice
			actual = example.new Client(example
					.new Service()).getUserName(1);
			
			assertThat(actual, is(expected));			

		}		

	}

}

 
Example Aspect in a JUnit test
/**  */
package com.octodecillion.jmockit.example;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Using AspectJ in a JUnit test.
 * <p>
 * For compile issue in Eclipse: {@link http://stackoverflow.com/questions/8958267/java-lang-verifyerror-expecting-a-stackmap-frame}
 * @see http://stackoverflow.com/questions/8958267/java-lang-verifyerror-expecting-a-stackmap-frame
 * 
 */
public class AspectJUnit {

	/**  the client we are testing */
	public class Client {
		private Service service;
		
		public Client(Service service) {
			this.service = service;
		}
		
		/** invoke the 'expensive' service. */
		public String getUserName(int n){
			return service.query(n);			
		}
		
	}
	
	/** the service that does integration stuff */
	public class Service {
			/**
			 * @param key 
			 * @return 
			 */
			public String query(int n) {				
				return values.get(n);
			}
			
			private final List<String> values = 
				Arrays.asList("first","second","third");
	}
	
	@Aspect
	static class TestAspect {
		
		@Around("call( * AspectJUnit.Service.query(..)) && args(i)")
		public String doQuery(ProceedingJoinPoint tjp, int i){
			return (i == 1) ? "Hello world!"
				: (String) tjp.proceed(new Object[]{i});
		}		
		
	}
	
	/**
	 * Nested test class.
	 *
	 */
	@RunWith(JUnit4.class)
	public static class UnitTest{
		private AspectJUnit example;
		
		/**   */
		@Test
		public void should_do_around_advice() {
			String expected = "Hello world!";
			String actual = example.new Service().query(1);
			assertThat(actual, is(expected));
			
			actual = example.new Client(example
					.new Service()).getUserName(1);
			
			assertThat(actual, is(expected));			

		}
		
		@org.junit.Before
		public void setup(){
			example = new AspectJUnit();
		}

	}	

}

 

Related Reading

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

JMockIt method not found in type when using Invocation arg

Strange I was writing a very simple JUnit test using JMockIt. But, it has a compile error.

I wanted to also invoke the original mocked target object in the test. In the state based Mockup API one does this by adding a mockit.Invocation as the first argument to the method signature.

	@Mock
	public String getV(Invocation invocation, String key) { ....... }

Then, the original mocked object is available via: invocation.getInvokedInstance().

It does not work in Eclipse 4.2. I copied the same code and opened the source in Eclipse 3.7. It works. Thus, the issue is Eclipse or a setup difference.

Update
May 19, 2013: I see that the classpath ordering is different as shown in the .classpath config file. Also, the JRE_CONTAINER is different, the one in the Eclipse 4.2 project is using JavaSE-1.7. That should have been jdk1.7.0_13. Will have to retest.
That wasn’t the issue.

Environment

  • Windows 7 64bit, AMD PC
  • JDK 1.7
  • Eclipse 4.2
  • JUnit 4
  • JMockIt 1.2
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Java JMockIt mocks via Spring DI

How to use Dependency Injected mock objects to allow Integration Testing of a Java application.

When working with some legacy code bases, the introduction of Dependency Injection has limitations. Thus, various forms of ‘instrumentation’ will be required to reach the “last mile”. A major difficulty with legacy code is instantiation of objects with the “new” operator.

One form of instrumentation is a modern Mocking framework, like JMockIt, another is the use of AOP with, for example, AspectJ.

As part of an evaluation of a possible approach I looked into using DI for data driven Integration Testing. Is it possible to use declarative specification of JMockIt mock objects? That is, can they be specified in a Spring XML bean configuration file and loaded via Spring Framework DI? This is in lieu of Using AspectJ to dependency inject domain objects with Spring or some other framework.

Short answer, yes. Useful technique? Probably not. But …

I was able to solve this by looking at the JMockIt source code for the mockit.internal.startup.JMockitInitialization class.

From JMockIt source repository:

final class JMockitInitialization
{
  ... snipped ...
  private void setUpStartupMocksIfAny()
   {
      for (String mockClassName : config.mockClasses) {
         Class<?> mockClass = ClassLoad.loadClass(mockClassName);

         //noinspection UnnecessaryFullyQualifiedName
         if (mockit.MockUp.class.isAssignableFrom(mockClass)) {
            ConstructorReflection.newInstanceUsingDefaultConstructor(mockClass);
         }
         else {
            new MockClassSetup(mockClass).setUpStartupMock();
         }
      }
   }
  ... snipped ...
}

See the “Using mocks and stubs over entire test classes and suites” in the tutorial for further info.

Turned out to be easy to create a Spring XML configuration and a simple mocked “hello world” proof of concept. The web server was instrumented dynamically!

Updates
One thing I could not figure out was how to destroy existing Mocks that were created in the Tomcat app server. Calling Mockit.tearDownMocks() had no effect. Admittedly, JMockIt is for use in JUnit based tests, so this may be pushing it.

Further reading

  1. Hermetic Servers This shows that the above idea is useful and not unique.
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Test Coverage Using JMockit

The JMockit Unit Testing library continues to astound. One new thing I discovered is its Coverage reporting.

Code Coverage
Code coverage is simply a measurement of what code has been actually run when tests are executed. There are many such measures, ramifications, and tools. Like testing itself, code coverage measurement is probably not done enough, or misused.

“Code coverage tells you what you definitely haven’t tested, not what you have.” — Mark Simpson in comment

Path Coverage
Plenty of coverage reporting tools out there. What this one also includes is Path coverage. This is different then branch or line coverage. Paths are possible execution paths from entry points to exit points. If you visualize a methods statements in a directed graph, paths are a enumeration of the possible edges traversed when that method is invoked. So, Path coverages is inclusive of Branch coverage. Well, I’m not a testing expert, so this may be way off.

Very surprising results. For example, you run a coverage report with a tool such as Cobertura or Emma and feel very happy that you exercised every line and branch with your tests. Then you run the same tests but use JMockit Coverage and discover your tests didn’t cover all the paths! Not only that your line coverage wasn’t so great either.

Report
JMockit explicitly gives you a report showing:

Path
Measures how many of the possible execution paths through method/constructor bodies were actually executed by tests.
The percentages are calculated as 100*NPE/NP, where NP is the number of possible paths and NPE the number of fully executed paths.

Line
Measures how much of the executable production code was exercised by tests. An executable line of code contains one or more executable segments.
The percentages are calculated as 100*NE/NS, where NS is the number of segments and NE the number of executed segments.

Data
Measures how many of the instance and static non-final fields were fully exercised by the test run. To be fully exercised, a field must have the last value assigned to it read by at least one test. The percentages are calculated as 100*NFE/NF, where NF is the number of non-final fields and NFE the number of fully exercised fields.

— from the JMockit coverage report HTML page

Other information is found by using the full HTML output option.

Example
A sample JMockit coverage report is here. Of course you can drill down into various parts of the html page. Like when you click on an exercised line you will get a list of what invoked that line.

Worth it?
Are the metrics such as Path coverage that this tool generates accurate? Is JMockit coverage a replacement for other tools such as Cobertura? I don’t know. For most projects, the resources would probably make the use of coverages generated by multiple tools prohibitive.

Evaluation
One possible approach to evaluating coverage tools is to just use actual real results of the target application. Use the list of bugs and correlate to a coverage tool report. Where were the bugs? Which tool gave the least measure for this location? True, a ‘bug’ is not always a code problem or limited to one ‘unit’, which is a what a unit test is targeted to.

Further Reading

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.