SamLewis.me Just another Java blog

April 10, 2012

Stamping Version Control Info in a Manifest File with Maven

Filed under: java,maven — Tags: — Sam @ 9:18 pm

I was reading Stamping Version Number and Build Time in a Properties File with Maven which has a a nice example of creating a properties file in a jar / war with the maven version and timestamp. That is pretty useful but I like to take a different approach:

  • Stamp the MANIFEST.MF file – it is the standard place for package-related metadata.
  • Stamp the revision number from the Version Control System (VCS)
  • Stamp the VCS branch

Stamping the VCS details allows anyone looking at the artifact to clearly see which branch and version of code was built. Developers can be sloppy about updating the maven version number but the revision number and VCS details never lie :-)

The buildnumber-maven-plugin will be used to populate the manifest items, here is the POM:

<project>
	<modelVersion>4.0.0</modelVersion>
	<groupId>me.samlewis</groupId>
	<artifactId>scm-stamp</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<scm>
		<connection>scm:svn:http://myproject.googlecode.com/svn/trunk</connection>
		<developerConnection>scm:svn:https://myproject.googlecode.com/svn/trunk</developerConnection>
		<url>http://myproject.googlecode.com/svn/trunk</url>
	</scm>
	<build>
		<plugins>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>buildnumber-maven-plugin</artifactId>
				<executions>
					<execution>
						<phase>validate</phase>
						<goals>
							<goal>create</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<doCheck>false</doCheck>
					<doUpdate>false</doUpdate>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
					<archive>
						<manifestEntries>
							<SCM-Revision>${buildNumber}</SCM-Revision>
							<SCM-Branch>${scmBranch}</SCM-Branch>
						</manifestEntries>
					</archive>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

The <scm> element sets up the version control system details,  the buildnumber-maven-plugin populates variables from the VCS and the maven-war-plugin is configured to add the additional manifest entries. This is the generated MANIFEST.MF file:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: SLewis
Build-Jdk: 1.6.0_21
SCM-Branch: trunk
SCM-Revision: 115

The above example is for a war project, for a jar project the maven-jar-plugin needs to be configured:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-jar-plugin</artifactId>
	<configuration>
		<archive>
			<manifestEntries>
				<SCM-Revision>${buildNumber}</SCM-Revision>
				<SCM-Branch>${scmBranch}</SCM-Branch>
			</manifestEntries>
		</archive>
	</configuration>
</plugin>

Happy manifest generation!

February 27, 2012

Testing a Web Service with JBehave and CXF

Filed under: java — Tags: , — Sam @ 8:50 pm

JBehave is a java framework for Behaviour-Driven Development (BDD). JBehave has Selenium support for browser based functional testing but it can also be used to test interfaces without a user interface. This post has an example of using JBehave and CXF to test a webservice, a public webservice to convert numbers to words will be used:

http://www.dataaccess.com/webservicesserver/numberconversion.wso?WSDL

This wsdl has an operation NumberToWords which simply converts a number to words e.g. 123 -> one hundred and twenty three – soapUI can easily invoke this webservice if you want to see it in action first.

CXF is an Open-Source Services Framework, it offers a whole lot more but we will just be using the cxf-codegen-plugin to generate a JAX-WS client to consume the webservice.

JBehave has supports Spring / Guice and PicoContainer Dependency Injection (DI) support, in this example we will use Guice.

JBehave can be tricky to configure when starting out but fortunately it comes has some handy maven archetypes to kick start a JBehave project, so lets use one to create our project, first run the command:

mvn archetype:generate -Dfilter=org.jbehave:jbehave

When prompted, enter the following:

Choose archetype:
1: remote -> org.jbehave:jbehave-groovy-archetype (An archetype to run multiple textual stories with steps classes written in Groovy.)
2: remote -> org.jbehave:jbehave-guice-archetype (An archetype to run multiple textual stories configured programmatically but with steps classes
 composed using Guice.)
3: remote -> org.jbehave:jbehave-pico-archetype (An archetype to run multiple textual stories configured programmatically but with steps classes
composed using Pico.)
<snip>
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 2
Choose org.jbehave:jbehave-guice-archetype version:
<snip>
14: 3.5.3
15: 3.5.4
16: 3.6-beta-1
17: 3.6-beta-2
18: 3.6-beta-3
Choose a number: 18: 15
Define value for property 'groupId': : me.samlewis.blog
Define value for property 'artifactId': : jbehave-cxf
Define value for property 'version': 1.0-SNAPSHOT: 1.0
Define value for property 'package': me.samlewis.blog: me.samlewis.blog.jbehavecxf
[INFO] Using property: jbehaveCoreVersion = 3.5.4
[INFO] Using property: jbehaveSiteVersion = 3.1.1
Confirm properties configuration:
groupId: me.samlewis.blog
artifactId: jbehave-cxf
version: 1.0
package: me.samlewis.blog.jbehavecxf
jbehaveCoreVersion: 3.5.4
jbehaveSiteVersion: 3.1.1
Y: Y
<snip>
[INFO] BUILD SUCCESSFUL

Now we can go ahead and build the project:

cd jbehave-cxf
mvn verify site

Hopefully you will see “BUILD SUCCESSFUL”.

Some irrelevant spring configuration is included in the this guice application so lets delete src\main\resources\me\samlewis\blog\jbehavecxf\my_steps.xml.

Next, lets create our story. First, rename src\main\resources\me\samlewis\blog\jbehavecxf\stories\my.story to number_to_words.story and change the contents to:

Scenario: one digit number is converted to words

Given a number of 4
When the number is converted to a word
Then the word is four

Scenario: two digit number is converted to words

Given a number of 23
When the number is converted to words
Then the words are twenty three

Scenario: three digit number is converted to words

Given a number of 945
When the number is converted to words
Then the words are nine hundred and forty five

Scenario: four digit number is converted to words

Given a number of 8361
When the number is converted to words
Then the words are eight thousand three hundred and sixty one

So we have four scenarios in our story. JBehave searches for Given / When / Then ‘Step’ annotations to match the text in our story when it runs so having not implemented any steps we expect the build to fail when this command is run:

mvn clean verify

The build fails but conveniently JBehave tells us the steps we need to implement:

Scenario: one digit number is converted to words
Given a number of 4 (PENDING)
When the number is converted to a word (PENDING)
Then the word is four (PENDING)
@Given("a number of 4")
@Pending
public void givenANumberOf4(){
 // PENDING
}
@When("the number is converted to a word")
@Pending
public void whenTheNumberIsConvertedToAWord(){
 // PENDING
}
@Then("the word is four")
@Pending
public void thenTheWordIsFour(){
 // PENDING
}

So lets go ahead to implement all of the steps, edit src\main\java\me\samlewis\blog\jbehavecxf\steps\MySteps.java changing the contents to:

package me.samlewis.blog.jbehavecxf.steps;

import static junit.framework.Assert.assertEquals;

import java.math.BigInteger;

import org.jbehave.core.annotations.Alias;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;

public class MySteps {
	private BigInteger number;
	private String result;

	@Given("a number of $number")
	public void givenANumber(BigInteger number){
		this.number = number;
	}

	@When("the number is converted to a word")
	@Alias("the number is converted to words")
	public void whenTheNumberIsConvertedToWords(){
		throw new IllegalStateException("TODO: implement me");
	}

	@Then("the word is $words")
	@Alias("the words are $words")
	public void thenTheWordIs(String words){
		assertEquals(words, result);
	}
}

The @Alias annotation can be used to make the stories more readable, in this example we use have singular and plural aliases. Variables are bound to method parameters for example in the thenTheWordIs() method the $words variable is bound to the words method parameter.

The whenTheNumberIsConvertedToWords() method currently just throws an IllegalStateException because we aren’t ready to call the web service just yet. So lets use cxf to generate classes to invoke our webservice, add this plugin config to our pom.xml file:

<plugin>
	<groupId>org.apache.cxf</groupId>
	<artifactId>cxf-codegen-plugin</artifactId>
	<version>2.3.1</version>
	<executions>
		<execution>
			<phase>generate-sources</phase>
			<configuration>
				<wsdlOptions>
					<wsdlOption>
						<wsdl>http://www.dataaccess.com/webservicesserver/numberconversion.wso?WSDL</wsdl>
					</wsdlOption>
				</wsdlOptions>
			</configuration>
			<goals>
				<goal>wsdl2java</goal>
			</goals>
		</execution>
	</executions>
</plugin>

Now, build again:

mvn clean verify

And the sourcecode to call this web service should be generated in target/generated-sources/cxf.

So now we can go ahead and implement the unimplemented method in our steps:

import java.net.MalformedURLException;
import java.net.URL;

import org.jbehave.core.annotations.Alias;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;

import com.dataaccess.webservicesserver.NumberConversion;
import com.dataaccess.webservicesserver.NumberConversionSoapType;
import com.google.inject.Inject;
import com.google.inject.name.Named;

public class MySteps {
	private BigInteger number;
	private String result;
	private NumberConversionSoapType numberConversionSoapType;

	@Inject
	public MySteps(@Named("number.conversion.wsdl") String wsdlLocation){
		try{
			NumberConversion numberConversion = new NumberConversion(new URL(wsdlLocation));
			numberConversionSoapType = numberConversion.getNumberConversionSoap();
		}
		catch (MalformedURLException e){
			throw new RuntimeException("Invalid wsdlLocation", e);
		}
	}

	@Given("a number of $number")
	public void givenANumber(BigInteger number){
		this.number = number;
	}

	@When("the number is converted to a word")
	@Alias("the number is converted to words")
	public void whenTheNumberIsConvertedToWords(){
		result = numberConversionSoapType.numberToWords(number);

		//remove trainling space
		result = result.trim();
	}

	@Then("the word is $words")
	@Alias("the words are $words")
	public void thenTheWordIs(String words){
		assertEquals(words, result);
	}
}

The constructor has Guice annotations to inject a property for the wsdl url and the whenTheNumberIsConvertedToWords() method invokes the numberToWords operation. There is an extra line to trim the result because the public web service result has a trailing space.

So, one last step is to configure guice, first create the file src/main/resources/config.properties with the contents:

number.conversion.wsdl=http://www.dataaccess.com/webservicesserver/numberconversion.wso?WSDL

Then edit the file /src/main/java/me/samlewis/blog/jbehavecxf/MyStories.java modifying the guice module inner class:

public static class StepsModule extends AbstractModule {

    @Override
    protected void configure() {

    	try{
		Properties properties = new Properties();
		properties.load(getClass().getResourceAsStream("/config.properties"));
		Names.bindProperties(binder(), properties);

		bind(MySteps.class).in(Scopes.SINGLETON);
	}
    	catch (IOException e){
    		throw new RuntimeException("Failed to load peoperties", e);
	}
    }
}

Guice is setup to load our properties file so the wsdl url can be injected. So now we can build again build again, one last time:

mvn clean verify

The build should succeed and a nice report written to target/jbehave/view/me.samlewis.blog.jbehavecxf.stories.number_to_words.html. You are probably going to want to run tests from your IDE during development, you can run MyStories as a JUnit test.

This post has barely scratched the surface of JBehave but it demonstrates that you can use JBehave to test programmatic interfaces such as Web Services / EJBs / Restful Services etc etc.

The sourcecode for this example can be downloaded here.

February 16, 2012

How the favicon broke our login

Filed under: java — Tags: , — Sam @ 9:05 pm

I was working for a large UK company which is a household name and my team were working on implementing a 3rd party Single Sign On solution replacing a homegrown one. The login / logout mechanism was provided out of the box by the SSO solution but we had to continue to set authentication token cookies just like the old perl login so we wrote a java servlet for login which set the new SSO cookie and all of the legacy cookies. When all of the consuming applications that used the legacy SSO mechanism moved to the new SSO platform we could ditch our bespoke login application and use the out of the box offering.

The legacy login url was kind of strange, it made no sense so we wanted to move people away from it but initially we would support 2 login urls:

  • Legacy – www.mycorp.co.uk/strange/legacy/url/login
  • New – sso.mycorp.co.uk/login
Both urls were configured with apache rules invoke a single webapp hosting our login / logout application. During the development we found out that the perl app would perform a login for any url apart from /logout and handle gets and posts – the legacy login url had to stay and behave exactly the same because we “aren’t sure who is using it” so our mappings in web.xml looked like this:
<servlet-mapping>
	<servlet-name>logout_handler</servlet-name>
	<url-pattern>/logout</url-pattern>
</servlet-mapping>
<servlet-mapping>
	<servlet-name>login_handler</servlet-name>
	<url-pattern>*</url-pattern>
</servlet-mapping>

In our dev environment the urls were not representative of live but they were in our QA environment, login worked perfectly in dev but as soon as we got out new login into QA it behaved strangely. Login worked on Internet Explorer, sometimes in Firefox and never in Chrome.

The team spent some time trying to work out what was going on, after many wasted hours we worked out that the browsers favicon.ico requests were causing the problem:

  1. User requests (POST) sso.mycorp.co.uk/login with a username and password
  2. Login succeeds and the response sets the SSO cookies
  3. Browser requests (GET) sso.mycorp.co.uk/favicon.ico
  4. Request is handled by the login servlet which clears your SSO cookies because the request doesnt contain a username / password

So the SSO cookies were cleared immediately after they were set resulting is the user not being logged in (in Chrome and Firefox some of the time). I guess IE ignores set-header from the response of favicon.ico requests. Not sure what was causing FF to behave inconsistently.

Anyway, a simple apache rule to intercept the favicon.ico requests and the problem was resolved with no real harm done.

In the end we had a succesful implementation and the new SSO solution was in place – after the overnight deployment we went for a few celebratory beers in our hotel bar at 6am – people eating their breakfast gave us some strange looks :-)

This issue was fundamentally caused by 2 bizarre requirements from the legacy perl application:

1) You can login with a get request

2) All requests (except /logout) must be handled by the login process

February 14, 2012

UUID to BigInteger

Filed under: java — Tags: , — Sam @ 11:05 pm

Today I had the requirement to create a unique transaction Id which must me a positive integer of 50 digits or less, that ruled out a UUID string but maybe it was possible to convert a UUID to a suitable decimal.

Collisions with randomly generated UUID’s are highly unlikely, according to wikipedia:

“Only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%. The probability of one duplicate would be about 50% if every person on earth owns 600 million UUIDs.”

That only holds true if there are no issues with the random algorithm, Java’s UUID.randomUUID() uses java.security.SecureRandom which is good enough for me.

A UUID represents a 128-bit value which so the maximum number as a positive integer would be:

= 2^128 = 340282366920938463463374607431768211456

That is 39 digits so that works for my 50 digits or less requirement.

Now to actually convert the UUID to a BigInteger, this is my utility class:

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.UUID;

public final class UuidUtil
{
	private UuidUtil()
	{
	}

	public static byte[] toByteArray(UUID uuid)
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(baos);

		try
		{
			dos.writeLong(uuid.getMostSignificantBits());
			dos.writeLong(uuid.getLeastSignificantBits());

			return baos.toByteArray();
		}
		catch (IOException e)
		{
			throw new RuntimeException(e);  //should never happen
		}
	}

	public static BigInteger toBigInteger(UUID uuid)
	{
		return new BigInteger(1, toByteArray(uuid));
	}
}

In toByteArray() we get write the most significant 64 bits from UUID to a DataOutputStream, then write the least significant 64 bits. The DataOutputStream is writing to an underlying ByteArrayOutputStream so we can get the bytes at the end of the method.

The toBigInteger() method simply converts the UUID to bytes then constructs a BigInteger. The 1 passed as the first argument of the BigInteger constructor is the signum and means the the BigInteger will be.

So a lets test of this utility class:

public static void main(String... args)
{
	for(int i = 0; i < 10; i++)
	{
		BigInteger result = UuidUtil.toBigInteger(UUID.randomUUID());
		System.out.println(result);
	}
}

When this class runs, this is the output:

21296035508720328449335133209314295423
274722916195131906374793179317240082774
104289978041632353131383939847405813299
311664747993489060466617613711755423113
256303865849504633392292205318822519341
26156960088707656665925032280696450135
251550234290735595417361324918168469451
199212202704710435325089402301665968133
195857127143045087032109883793450556303
233512240909595403554561012650413133419

There are no collisions there atleast!

This is probably a pointless exercise since I am using the  type 4 (pseudo randomly generated) UUID I may as well have used SecureRandom and avoided the overhead of the UUID’s 6 bits for the version and variant :-)

February 13, 2012

That’s not how you create a Thread!

Filed under: java — Sam @ 10:57 pm

I stumbled across a blog javaeschool.com which has a post: Java Thread Example, unfortunately the example is not great:

/**
* @author javaeschool.com
*/
public class JavaThreadExample {

	public static void main(String[] args) {
		// Thread Class object
		Thread th = new Thread();
		// Array with name
		String name[] = { "Aparna", "Parvati", "Surbhi", "Gauri", "Saurabh" };
		System.out.println("Each name in the array " + "will print after 5 seconds : ");
		try {
			for (int i = 0; i < 5; i++) {
				System.out.println(name[i]);
				// Thread sleep for 5000 miliseconds
				th.sleep(5000);
			}
		} catch (InterruptedException e) {
			System.out.println("Thread interrupted!!!!!!!");
			e.printStackTrace();
		}
	}
}

It is an example of how to sleep in the current thread and pointlessly create an instance of the Thread class to access a static method in a non static way (Thread.sleep())

So here is my simple example of Threads:

/**
* @author sam
*/
public class JavaThreadExample {

	public static void main(String[] args) {

		Runnable runnable = new Runnable() {

			@Override
			public void run() {
				for(int i = 10; i >= 0; i-- ){
					try {
						System.out.println(Thread.currentThread().getName() + " - " + i);
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						//ignore
					}
				}
				System.out.println(Thread.currentThread().getName() + " - done");
			}
		};

		Thread thread1 = new Thread(runnable, "Thread 1");
		Thread thread2 = new Thread(runnable, "Thread 2");

		thread1.start();
		thread2.start();

		System.out.println("Exiting main method");
	}
}

2 threads are created which count down from five to zero with a second pause between, this is the output:

Thread 1 - 5
Exiting main method
Thread 2 - 5
Thread 1 - 4
Thread 2 - 4
Thread 1 - 3
Thread 2 - 3
Thread 1 - 2
Thread 2 - 2
Thread 1 - 1
Thread 2 - 1
Thread 1 - 0
Thread 2 - 0
Thread 1 - done
Thread 2 - done

You can see the main method exiting and the 2 threads counting down.

Since java 1.5 we have had the java.util.concurrent package which makes simple multi-threaded programming a little easier:

public static void main(String[] args) {

    Runnable runnable = new Runnable() {
        .... snip - same as last example ....
    };

    ExecutorService pool = Executors.newFixedThreadPool(2);

    for (int i = 0; i < 2; i++) {
        pool.execute(runnable);
    }
    pool.shutdown();

    System.out.println("Exiting main method");
}

Hopefully my threading examples are a bit better than javaeschool.com :-)

February 12, 2012

Some of the best Jenkins Plugins

Filed under: continuous integration,java — Tags: — Sam @ 11:55 am

Jenkins is a brilliant Continuous Integration server and has a thriving plugin ecosystem. Here are some of the best.

Wall Display Plugin

Back in 2004 we setup CI with cruisecontrol and we wanted to order an Ambient Orb to display the build status bur couldn’t find one  for sale in the UK. Things have moved on and we can now get a PC and TV and display much more information with this beautiful plugin.

Wall Display in action

Green Balls

I have never understood Jenkins blue colour choice for a successful builds, the green balls plugin is one of the first plugins I install on a new Jenkins server.

 

Build Timeout

If your build gets ‘stuck’ once in a while the Build Timeout plugin can be used to abort it after a specified period.

 

Maven Dependency Update trigger

Periodically checks if a projects SNAPSHOT dependencies have been updated for a project and triggers a build. This is useful if you have a snapshot dependency from a 3rd party or another team in your organisation with a separate jenkins install.

 

ThinBackup

The thinbackup plugin is more sophisticated than the Backup Plugin because it only backs up the jenkins configuration, not the entire workspace. Also thinBackup can be scheduled.

 

Port Allocator Plugin

If your build needs unique ports e.g. integration tests that start an application server this plugin can allocate them for you. You can also specify fixed ports which prevents jobs running concurrently that require the same port.

February 11, 2012

Unit Test the Untestable with Powermock

Filed under: java,unit testing — Tags: , — Sam @ 1:30 am

Powermock extends the mock libraries Mockito and EasyMock to add the ability to test code that cant usually be tested by these libraries. Powermock allows you to:

  • mock static methods
  • mock constructors
  • mock final classes
  • mock final methods
  • mock private methods
  • suppress static initializers

The above are usually the enemy of the unit tester but with powermock you can test legacy code full of singletons, service locators, factories etc. I would prefer refactor the hard to test code but that is not always practical.

I am going to write some shoddy code that would normally be considered untestable and then write a unit test for it with PowerMock, Mockito and JUnit, lets say we want to unit test UntestableService which delegates to a DAO to get a user and performs some trivial logic:

public final class UntestableService
{
	public User getUser(long id)
	{
		User user = UnmockableDao.getInstance().getUser(id);

		if(user == null)
		{
			throw new RuntimeException("user not found");
		}
		else
		{
			return user;
		}
	}
}

The UnmockableDao class in the above code is a singleton and that would usually mean that above class cant be unit tested. Singletons seem very popular in legacy code but are now are generally considered bad practice, there is a question on stackoverflow “What is so bad about Singletons?” which discusses the reasons. If we used Dependency Injection the DAO would be injected through a constructor / setter making unit testing possible without powermock.

Lets make UnmockableDao as difficult as possible to mock:

import java.io.FileReader;
import java.sql.*;
import java.util.Properties;

public final class UnmockableDao //final class
{
	private static final UnmockableDao INSTANCE;

	private final Connection conn;

	static //static initializer
	{
		INSTANCE = new UnmockableDao();
	}

	private UnmockableDao() //private constructor
	{
		try
		{
			Properties properties = new Properties();
			properties.load(new FileReader("/somepath/somefile.config"));

			Class.forName(properties.getProperty("db.driver"));

			conn = DriverManager.getConnection(properties.getProperty("db.url"));
		}
		catch (Exception e)
		{
			throw new IllegalStateException(e);
		}
	}

	public static final UnmockableDao getInstance() //static and final
	{
		return INSTANCE;
	}

	public final User getUser(long id) //final method
	{
		try
		{
			ResultSet rs = conn.createStatement().executeQuery("select * from users where id = " + id);

			if(rs.next())
			{
				return new User(rs.getString("username"));
			}
			else
			{
				return null;
			}
		}
		catch (SQLException e)
		{
			throw new RuntimeException(e);
		}
	}
}

Most mock object frameworks wouldn’t be able to mock UnmockableDao because it is a final class,  it has a static initializer, private constructor, static method and final method.

PowerMock to the rescue! Here is a testcase for UntestableService which mocks UnmockableDao:

import static org.junit.Assert.*;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.*;

import org.junit.*;
import org.junit.runner.*;
import org.powermock.core.classloader.annotations.*;
import org.powermock.modules.junit4.PowerMockRunner;

@SuppressStaticInitializationFor("UnmockableDao") //pretty self explanatory
@PrepareForTest(UnmockableDao.class) //allows PowerMock to mock static methods / final methods on this class
@RunWith(PowerMockRunner.class) //required for PowerMock to work
public class TestUntestableService
{
	private UnmockableDao dao;

	private UntestableService service;

	@Before
	public void setUp()
	{
		mockStatic(UnmockableDao.class); //mock all static methods on this class

		dao = mock(UnmockableDao.class); //standard mockito

		when(UnmockableDao.getInstance()).thenReturn(dao); //standard mockito except the method is static

		service = new UntestableService();
	}

	@Test
	public void testGetUser_Exists()
	{
		long userId = 123L;

		User expectedUser = new User("Jamie");

		//setup the mock to return expectedUser when getUser() is invoked with userId
		when(dao.getUser(userId)).thenReturn(expectedUser);

		User actualUser = service.getUser(userId);

		assertNotNull(actualUser);
		assertEquals("Jamie", actualUser.getName());
	}

	@Test
	public void testGetUser_DoesntExist()
	{
		long userId = 456L;

		//setup the mock to return null when getUser() is invoked with null
		when(dao.getUser(userId)).thenReturn(null);

		try
		{
			service.getUser(userId);

			fail();
		}
		catch (RuntimeException e)
		{
			assertEquals("user not found", e.getMessage());
		}
	}
}

I have tried to add comments to the line that do the PowerMock magic. Here are the green JUnit results:

Test Results

There is a fair bit of code to mock this super hard to test singleton and on some legacy codebases the unit tests could soon get unwieldy. One place PowerMock could useful is if your application uses a particular 3rd party library which is untestable with most mock libraries, it could save sacrificing good design for the sole purpose of testability.

Happy mocking!

You can download the example project here.

February 10, 2012

Stop Calling it a Unit Test

Filed under: integration testing,java,unit testing — Sam @ 6:58 pm

One of my (many) pet hates is developers incorrectly calling tests ‘Unit Tests’. Wikipedia defines unit testing as:

“a method by which individual units of source code are tested to determine if they are fit for use. A unit is the smallest testable part of an application.

Your test is not a unit test if it:

  • connects to a network
  • connects to a database
  • wont run at the same time as any of your other ‘unit tests’
  • uses the file system
  • requires special setup (e.g. environment variables, properties files) to run it.
  • takes more than a couple of seconds to run

I am not saying that these kind of tests aren’t valuable, but I call them ‘Integration Tests’. Wikipedia defines integration testing as:

“the phase in software testing in which individual software modules are combined and tested as a group. It occurs after unit testing”

A couple of years ago I started on a project where the lead developer was incredibly proud of their Unit Test suite and code coverage, these tests all pretty much followed this pattern:

  • Drop a database
  • Create the database
  • Populate the database with some test data
  • Start the application
  • Call one of the applications webservices
  • Check the response
  • Check  the database
  • Stop the application

It was a very impressive and comprehensive Integration Test suite but there was not a single Unit Test :-) I gradually managed introduce Dependency Injection to make the codebase easier to unit test, introduced Mock Object frameworks to the team and built up a suite of unit tests in addition to the integration tests.

February 9, 2012

Fluent Assertions with FEST (bye bye Hamcrest!)

Filed under: java,unit testing — Tags: , , — Sam @ 8:39 pm

FEST (Fixtures for Easy Software Testing) includes Fluent Assertions which can be used to create custom matchers for Junit / TestNG tests. FEST Assertions are an alternative to the popular Hamcrest framework but takes a different approach.

Here is an example that shows the equivalent test with FEST Assertions to one with Hamcrest which you may already use. Given this enum:

public enum Cheese {
	MILD_CHEDDAR("Mild Cheddar", 2),
	EMMENTAL("Emmental", 6),
	PARMIGIANO_REGGIANO("Parmigiano-Reggiano", 9);

	private final String name;
	private final int strength;

	private Cheese(String name, int strength){
		this.name = name;
		this.strength = strength;
	}

	public String getName() {
		return name;
	}

	public int getStrength() {
		return strength;
	}
}

Here is a simple  JUnit test for the enum written with Hamcrest:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.isOneOf;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;

import org.junit.Test;

public class HamcrestTest {

	@Test
	public void testHamcrest() throws Exception{

		Cheese myCheese = Cheese.EMMENTAL;

		assertThat(myCheese, notNullValue());
		assertThat(myCheese, not(isOneOf(Cheese.MILD_CHEDDAR, Cheese.PARMIGIANO_REGGIANO)));
		assertThat(myCheese, equalTo(Cheese.EMMENTAL));

		assertThat(myCheese.getStrength(), lessThan(Cheese.PARMIGIANO_REGGIANO.getStrength()));
		assertThat(myCheese.getStrength(), greaterThan(0));
		assertThat(myCheese.getStrength(), lessThanOrEqualTo(10));
		assertThat(myCheese.getStrength(), equalTo(6));

		assertThat(myCheese.getName(), endsWith("al"));
		assertThat(myCheese.getName(), isOneOf("jada", "Emmental"));
		assertThat(myCheese.getName(), startsWith("E"));
		assertThat(myCheese.getName(), equalToIgnoringCase("emMeNtaL"));
		assertThat(myCheese.getName(), equalTo("Emmental"));
	}
}

And here is the same test written with FEST Assertions:

import static org.fest.assertions.Assertions.assertThat;

import org.junit.Test;

public class FestAssertTest {

	@Test
	public void testFest() throws Exception{

		Cheese myCheese = Cheese.EMMENTAL;

		assertThat(myCheese).isNotNull()
						    .isNotIn(Cheese.MILD_CHEDDAR, Cheese.PARMIGIANO_REGGIANO)
						    .isEqualTo(Cheese.EMMENTAL);

		assertThat(myCheese.getStrength()).isLessThan(Cheese.PARMIGIANO_REGGIANO.getStrength())
										  .isGreaterThan(0)
										  .isLessThanOrEqualTo(10)
										  .isEqualTo(6);

		assertThat(myCheese.getName()).endsWith("al")
									  .isIn("jada", "Emmental")
									  .startsWith("E")
									  .isEqualToIgnoringCase("emMeNtaL")
									  .isEqualTo("Emmental");
	}
}

FEST assertions have some advantages over Hamcrest:

  • Only one static import is required – less code
  • IDE Auto completion can be used due to the method chaining approach

If you like to write your unit test assertions with hamcrest, you are going to love FEST Assertions!

You can download the example project here.

February 8, 2012

Java Open Source Swear Count

Filed under: java — Sam @ 8:43 pm

People have done some analysis on swear counts in the linux kernel, here then here:

Linux Kernel Swear Counts

The swear count increases over time but so do the lines of code. I wonder if any of the java librarys have swear words in the source files…

The java community now has a massive amount of sourcecode hosted in the maven repository with many projects uploading source jars so it must be possible to download all source jars and analyse them for cursing.

But we also have websites like grepcode.com which make all of this source available over the web so maybe google indexes the entire site so we can quickly get some curse counts:

Word Google Query Count
fuck site:grepcode.com fuck about 45
shit site:grepcode.com shit about 1,230
crap site:grepcode.com crap -crap4j about 3,620
bastard site:grepcode.com bastard 3 results

Interestingly there is a lot of shit and crap but not much fuck and bastard – I guess shit and crap are considered suitable for java sourcecode.

It seems like fuck and bastard are reserved for some particularly shoddy code, so lets check out a few examples:

A popular connection pool, c3p0 / c3p0 / 0.9.1.2 / com.mchange.v2.async.CarefulRunnableQueue:

//System.err.println(this.getName() + ": Some bastard used the deprecated stop() method to kill me!!!!");

reflections / 0.9.5-RC2 / org.reflections.util.ClasspathHelper:

catch (MalformedURLException e) { /*fuck off*/ }

org.apache.tapestry / tapestry-component-report / 5.0.19 / org.apache.tapestry.mojo.ParametersDoclet:

// Enough of this static method bullshit. What the fuck were they thinking?

xalan / xalan / 2.7.0 / org.apache.xalan.xsltc.dom.BitArray:

/**
* This method returns the Nth bit that is set in the bit array. The
* current position is cached in the following 4 variables and will
* help speed up a sequence of next() call in an index iterator. This
* method is a mess, but it is fast and it works, so don't fuck with it.
*/

com.google.code.svenson / svenson / 1.4.0 / org.svenson.util.JSONPathUtil:

// XXX: use inefficient recursive call.. fuck arrays..

Surely there must be more fucks and bastards – google bot probably doesn’t index the whole of grepcode.com. A future project might be to download the entire maven repository and write a shell script to find the swear words; find -name and zgrep should do the job :-)

Older Posts »

Powered by WordPress