Today I found out that schmidt.devlib.org has been eaten by the great Noodly One in the sky. A real shame it was a very useful resource for Java developer.
Hopefully it has found a new home.
Thursday, 29 October 2009
Tuesday, 27 October 2009
Mocking System Classes
Today I answered a question about mocking system classes in Java on Stack Overflow. I found the documentation for doing this somewhat limited, so I'm going to rework and repost my answer here.
First things first. If you have to mock system classes then do you have anything slightly smelly in your design? Can you work the direct link between the two out by say introducing a facade between the real dependency (java.lang.System) and the SUT.
Assuming that you can not or do not want to then you have at least two options: PowerMock and JMockIt.
Lets first make a class to test EnvOMatic. EnvOMatic has one method, clean This loads a value from the Environment and cleans of dirty words.
public class EnvOMatic {
public String clean(String key) {
String value = System.getenv(key);
if (value==null) {
return null;
}
return value.replaceAll("Groovy", "naughty");
}
}
PowerMock
Power Mock has some decent documentation for mocking system classes, but lets show an example of it
here.
package playtest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.legacy.PowerMockRunner;
import static org.powermock.api.easymock.PowerMock.*;
import static org.easymock.EasyMock.*;
import static junit.framework.Assert.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest( { EnvOMatic.class })
public class TestPowerMock {
@Test
public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
mockStatic(System.class);
final String key = "boo";
final String expected = "Bye";
expect(System.getenv(key)).andReturn(expected);
replayAll();
assertEquals(expected, new EnvOMatic().clean(key));
verifyAll();
}
}
So in this we tell JUnit to use the PowerMock runner, then specify the SUT that uses the System class via annotations. Then in the test class we inform PowerMock that we are mocking java.lang.System and finally use it as we would use any other EasyMock mock.
One thing that caught me out was that the JUnit 4.7 provided in the "With Dependencies" download did not work. JUnit 4.4 shipped Eclipse did.
JMockIt
Unlike PowerMock above I could not find any documentation on how to do this. The code below is various examples super glued together until it worked.
import org.junit.*;
import org.junit.runner.RunWith;
@RunWith(JMockit.class)
public class TestJMockIt {
@Test
public void assertThatMockingOfFinalSystemClassesWorks() {
Mockit.setUpMocks(MockSystem.class);
final String key = "boo";
final String expected = "Bye";
MockSystem.put(key, expected);
assertEquals(expected, new EnvOMatic().clean(key));
}
@MockClass(realClass = System.class)
public static class MockSystem {
static Map env = new HashMap();
static void put(String key, String value) {
env.put(key, value);
}
@Mock
public static String getenv(String key) {
return env.get(key);
}
}
}
One thing to note about this is that we are not mocking but stubbing java.lang.System. Now in this case I don't think this is a problem.
To make this work we need to use a custom runner again, this time JMockit. This runner does requires JUnit 4.5 or above.
Then we create a class with static methods stubs defined.
Finally we inform MockIt of the stub implementation.
So there you have two ways of stubbing and mocking java.lang.System. They both have same restriction - a custom runner, and I'm sure they are equally as powerful, so the choice of which to use will depend solely on your API preference.
First things first. If you have to mock system classes then do you have anything slightly smelly in your design? Can you work the direct link between the two out by say introducing a facade between the real dependency (java.lang.System) and the SUT.
Assuming that you can not or do not want to then you have at least two options: PowerMock and JMockIt.
Lets first make a class to test EnvOMatic. EnvOMatic has one method, clean This loads a value from the Environment and cleans of dirty words.
public class EnvOMatic {
public String clean(String key) {
String value = System.getenv(key);
if (value==null) {
return null;
}
return value.replaceAll("Groovy", "naughty");
}
}
PowerMock
Power Mock has some decent documentation for mocking system classes, but lets show an example of it
here.
package playtest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.legacy.PowerMockRunner;
import static org.powermock.api.easymock.PowerMock.*;
import static org.easymock.EasyMock.*;
import static junit.framework.Assert.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest( { EnvOMatic.class })
public class TestPowerMock {
@Test
public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
mockStatic(System.class);
final String key = "boo";
final String expected = "Bye";
expect(System.getenv(key)).andReturn(expected);
replayAll();
assertEquals(expected, new EnvOMatic().clean(key));
verifyAll();
}
}
So in this we tell JUnit to use the PowerMock runner, then specify the SUT that uses the System class via annotations. Then in the test class we inform PowerMock that we are mocking java.lang.System and finally use it as we would use any other EasyMock mock.
One thing that caught me out was that the JUnit 4.7 provided in the "With Dependencies" download did not work. JUnit 4.4 shipped Eclipse did.
JMockIt
Unlike PowerMock above I could not find any documentation on how to do this. The code below is various examples super glued together until it worked.
import org.junit.*;
import org.junit.runner.RunWith;
@RunWith(JMockit.class)
public class TestJMockIt {
@Test
public void assertThatMockingOfFinalSystemClassesWorks() {
Mockit.setUpMocks(MockSystem.class);
final String key = "boo";
final String expected = "Bye";
MockSystem.put(key, expected);
assertEquals(expected, new EnvOMatic().clean(key));
}
@MockClass(realClass = System.class)
public static class MockSystem {
static Map
static void put(String key, String value) {
env.put(key, value);
}
@Mock
public static String getenv(String key) {
return env.get(key);
}
}
}
One thing to note about this is that we are not mocking but stubbing java.lang.System. Now in this case I don't think this is a problem.
To make this work we need to use a custom runner again, this time JMockit. This runner does requires JUnit 4.5 or above.
Then we create a class with static methods stubs defined.
Finally we inform MockIt of the stub implementation.
So there you have two ways of stubbing and mocking java.lang.System. They both have same restriction - a custom runner, and I'm sure they are equally as powerful, so the choice of which to use will depend solely on your API preference.
Labels:
mock,
stack overflow,
unit testing
Thursday, 22 October 2009
*headbash*
I got sucked into the evil time vortex that is StackOverflow again and decided to have a go on a PMD question.
My god people put some sodding docs up.
I spend the last few hours digging about for any documentation that I could find on the tree structure and just could not find a damn thing. I had to spend my time scanning other peoples rules to attempt to work out what was going on.
So please developers of open source projects think for a few seconds about the poor bastards that actually use your software and invest a little time into the very unsexy act of writing documentation.
Thanks.
My god people put some sodding docs up.
I spend the last few hours digging about for any documentation that I could find on the tree structure and just could not find a damn thing. I had to spend my time scanning other peoples rules to attempt to work out what was going on.
So please developers of open source projects think for a few seconds about the poor bastards that actually use your software and invest a little time into the very unsexy act of writing documentation.
Thanks.
Labels:
documentation,
pmd,
rant,
stack overflow
Tuesday, 20 October 2009
My Nifty Idea
I have had a cool idea floating at the back of my mind for a little while and today as I have work I really don't want to do I worked out how to make it work and have thrown together a prototype. So first some background. I find myself writing a fair amount of database code. A lot of this is simple wrappers around a oracle package. The JDBC gods demand a fair amount of boiler plate. Even without going all the way to a ORM tool like Hibernate I know APIs exist to reduce said boilerplate but I've always felt (rightly or not) that I'd still end up doing a fair bit of boilerplate code even so or they were tied to an API I don't already use (i.e. Spring JDBC is slightly tried to Spring). I know the proper answer is likely to bite the bullet and use Spring. But sod that, I want to roll my own.
Mmm. Sorry slipping into irrelevant babbling. What I want out of an API is to define an interface and have that magically fill in the blanks. So for example if I define:
then all I'd have to do would be add some annotations to tell the Magic what I want and it would go ahead and make it happen. So today I created a prototype.
First the annotation:
@Retention(RetentionPolicy.RUNTIME)
public @interface Execute {
String script();
}
You then annotate the method you want to be magical.
Integer getCount();
}
Next the magic. Note: I'm using a Guice provider to get hold of the database. I'm not 100% that is the right way to go as while I'm very likely to use Guice do I really want to tie the implementation down to Guice? This play test of an implementation can only return void or Integer. If I was to go forward with this I'd have to get it to be able to return all primitive types at least and ideally be able to marshal complex types. Likely via annotations in the complex types. Maybe what I really want is JPA.
private void close(Statement s) {
if (s == null) {
return;
}
try {
s.close();
} catch(SQLException sqle) {
log.log(Level.WARNING, "Failed to close statement", sqle);
}
}
}
Next a helper class to handle database access.
ds.close();
}
}
And finally some magic:
public static void main(String argv[]) throws Exception {
ExampleDatabaseProvider dbProvider =
new ExampleDatabaseProvider(
"jdbc.driver","username", "password", "jdbc:database");
Queue example = (Queue)Proxy.newProxyInstance(
KickStart.class.g etClassLoader(),
new Class[] {Queue.class},
new QuickAndDirtySQLHandler(dbProvider));
System.out.println(example.getCount());
dbProvider.close();
}
}
I think that would be much better than raw JDBC for projects that demand the use of stored procedures (like all projects at my current employer). I should really look at how JPA handles forced use of stored procedures.
I think this is a cool idea and I plan to run with it (if I can find the time). I'll post updates here under the tag magic-procedures. The GitHub site is: http://github.com/mlk/magic-procedures and the public repository is git@github.com:mlk/magic-procedures.git
Mmm. Sorry slipping into irrelevant babbling. What I want out of an API is to define an interface and have that magically fill in the blanks. So for example if I define:
public interface Queue { int getCount();
}
then all I'd have to do would be add some annotations to tell the Magic what I want and it would go ahead and make it happen. So today I created a prototype.
First the annotation:
package playtest;import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Execute {
String script();
}
You then annotate the method you want to be magical.
package playtest;public interface Queue {
@Execute(script="{? = call Queue.getCount}")Integer getCount();
}
Next the magic. Note: I'm using a Guice provider to get hold of the database. I'm not 100% that is the right way to go as while I'm very likely to use Guice do I really want to tie the implementation down to Guice? This play test of an implementation can only return void or Integer. If I was to go forward with this I'd have to get it to be able to return all primitive types at least and ideally be able to marshal complex types. Likely via annotations in the complex types. Maybe what I really want is JPA.
package playtest;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.lang.reflect.Method;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.inject.Provider;
public class QuickAndDirtySQLHandler implements InvocationHandler {
private final Logger log = Logger.getLogger(getClass().getName());
private final Provider connectionProvider;
public QuickAndDirtySQLHandler(final Provider connectionProvider) {
this.connectionProvider = connectionProvider;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Execute execute = method.getAnnotation(Execute.class);
if (execute == null) {
throw new IllegalStateException("Required annotation missing!");
}
boolean returnsValue = false;
if (method.getReturnType().equals(Integer.c lass)) {
returnsValue = true;
}
Connection connection = connectionProvider.get();
CallableStatement statement = null;
try {
statement = connection.prepareCall(execute.script()) ;
if (returnsValue) {
statement.registerOutParameter(1, Types.INTEGER);
}
statement.execute();
if (returnsValue) {
return statement.getInt(1);
} else {
return null;
}
} finally {
close(statement);
connection.close();
}
}
private final Logger log = Logger.getLogger(getClass().getName());
private final Provider
public QuickAndDirtySQLHandler(final Provider
this.connectionProvider = connectionProvider;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Execute execute = method.getAnnotation(Execute.class);
if (execute == null) {
throw new IllegalStateException("Required annotation missing!");
}
boolean returnsValue = false;
if (method.getReturnType().equals(Integer.c
returnsValue = true;
}
Connection connection = connectionProvider.get();
CallableStatement statement = null;
try {
statement = connection.prepareCall(execute.script())
if (returnsValue) {
statement.registerOutParameter(1, Types.INTEGER);
}
statement.execute();
if (returnsValue) {
return statement.getInt(1);
} else {
return null;
}
} finally {
close(statement);
connection.close();
}
}
private void close(Statement s) {
if (s == null) {
return;
}
try {
s.close();
} catch(SQLException sqle) {
log.log(Level.WARNING, "Failed to close statement", sqle);
}
}
}
Next a helper class to handle database access.
package playtest.db;import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;
import com.google.inject.Provider;
public class ExampleDatabaseProvider implements Provider{
private final BasicDataSource ds = new BasicDataSource();
public ExampleDatabaseProvider(String driver, String username,
String password, String url) {
ds.setDriverClassName(driver);
ds.setUsername(username);
ds.setPassword(password);
ds.setUrl(url);
ds.setMaxActive(1);
ds.setDefaultAutoCommit(false);
}
@Override
public Connection get() {
try {
return ds.getConnection();
} catch(SQLException sqle) {
// Switch to a throwing provider?
throw new IllegalStateException(sqle);
}
}
public void close() throws SQLException {String password, String url) {
ds.setDriverClassName(driver);
ds.setUsername(username);
ds.setPassword(password);
ds.setUrl(url);
ds.setMaxActive(1);
ds.setDefaultAutoCommit(false);
}
@Override
public Connection get() {
try {
return ds.getConnection();
} catch(SQLException sqle) {
// Switch to a throwing provider?
throw new IllegalStateException(sqle);
}
}
ds.close();
}
}
And finally some magic:
package playtest;import java.lang.reflect.Proxy;
import playtest.db.ExampleDatabaseProvider;
public class KickStart {public static void main(String argv[]) throws Exception {
ExampleDatabaseProvider dbProvider =
new ExampleDatabaseProvider(
"jdbc.driver","username", "password", "jdbc:database");
Queue example = (Queue)Proxy.newProxyInstance(
KickStart.class.g
new Class[] {Queue.class},
new QuickAndDirtySQLHandler(dbProvider));
System.out.println(example.getCount());
dbProvider.close();
}
}
I think that would be much better than raw JDBC for projects that demand the use of stored procedures (like all projects at my current employer). I should really look at how JPA handles forced use of stored procedures.
I think this is a cool idea and I plan to run with it (if I can find the time). I'll post updates here under the tag magic-procedures. The GitHub site is: http://github.com/mlk/magic-procedures and the public repository is git@github.com:mlk/magic-procedures.git
Labels:
from dot-plan,
jdbc,
magic-procedures,
oracle,
store procedures,
teh codez
Code now on GitHub
I need to play with Git for a bit as I just don't understand what all the fuss is about. So I've thrown the code I've written for this blog on to GitHub. The public repository is:
git://github.com/mlk/ihaztehcodez.git
git://github.com/mlk/ihaztehcodez.git
JUnit 4.7 - TemporaryFolder
JUnit 4.7 adds a cool looking new feature - Rules. These should get rid of the need to write a new Runner every time you want something nifty to happen.
One of the rules is TemporaryFolder. This automatically creates and destroys a temporary folder at the start and end of a test. A neat extra and something I'd already thrown together for my own use. However my version did one thing different - it destroyed on start up not shut down. Why? The same reason my database tests do this. When testing I can quickly go back to any test and check the files it created and attempt to work out why a test is failing.
One of the rules is TemporaryFolder. This automatically creates and destroys a temporary folder at the start and end of a test. A neat extra and something I'd already thrown together for my own use. However my version did one thing different - it destroyed on start up not shut down. Why? The same reason my database tests do this. When testing I can quickly go back to any test and check the files it created and attempt to work out why a test is failing.
Labels:
junit,
unit testing
Mocking a Get/Set Pair using EasyMock
Once again I'm going to tart up a post of SO and throw it on here:
Say you have an interface with a get/set pair that get populated and retrieved. And you need these to match.
When it comes to testing items that depend on this you need to either - be able to know the get/set values in advance or write a little wrapper to remember the get/sets. In order to simplify this I humbly present:
public class GetSetAnswers<T> {
private T value;
public IAnswer<Object> set() {
return new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
Object[] arguments = getCurrentArguments();
value = (T) arguments[0];
return null;
}
};
}
public IAnswer<T> get() {
return new IAnswer<T>() {
@Override
public T answer() throws Throwable {
return value;
}
};
}
}
You can then use it thusly:
public class TestGetSet {
@Test
public void testSetGet() {
GetSetAnswers<Integer> value = new GetSetAnswers<Integer>();
GetSetId id = createMock(GetSetId.class);
id.setID(anyInt());
expectLastCall().andAnswer(value.set());
expect(id.getID()).andAnswer(value.get());
replay(id);
int generatedValue = (int) (Math.random() * 100.0);
id.setID(generatedValue);
Assert.assertEquals(generatedValue, id.getID());
verify(id);
}
}
Say you have an interface with a get/set pair that get populated and retrieved. And you need these to match.
public interface GetSetId {
public int getID();
public void setID(int id);
public void somethingThatMakesThisNotAValueObject();
}public int getID();
public void setID(int id);
public void somethingThatMakesThisNotAValueObject();
When it comes to testing items that depend on this you need to either - be able to know the get/set values in advance or write a little wrapper to remember the get/sets. In order to simplify this I humbly present:
public class GetSetAnswers<T> {
private T value;
public IAnswer<Object> set() {
return new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
Object[] arguments = getCurrentArguments();
value = (T) arguments[0];
return null;
}
};
}
public IAnswer<T> get() {
return new IAnswer<T>() {
@Override
public T answer() throws Throwable {
return value;
}
};
}
}
You can then use it thusly:
public class TestGetSet {
@Test
public void testSetGet() {
GetSetAnswers<Integer> value = new GetSetAnswers<Integer>();
GetSetId id = createMock(GetSetId.class);
id.setID(anyInt());
expectLastCall().andAnswer(value.set());
expect(id.getID()).andAnswer(value.get());
replay(id);
int generatedValue = (int) (Math.random() * 100.0);
id.setID(generatedValue);
Assert.assertEquals(generatedValue, id.getID());
verify(id);
}
}
Labels:
easymock,
get/set,
mutator,
stack overflow,
teh codez
Thursday, 1 October 2009
Integration vs Unit test for the database layer
A commonly posted question on Stack Overflow is how to unit testing the database layer. Any question about this generally ends up with two diverse answers. The first is that all database activities should be mocked and tested during integration testing, the second is that a real database should be used.
I feel that testing against a database is important and should be done frequently. As it needs to be done frequently it should be quick to set up and execute. Now setting up a database may sound like work, but if all developers have access to a dedicated database that sits either on the local machine or on a decent sized box in the background and the dataset are restricted to use what is reliant to the test then this take little time to connect to and set up.
As I'm a lazy git I don't really want to be using different technologies for different sets of tests. Any test that wants to run frequently and is fast to run just becomes a JUnit test.
So finally when should I write it? Well I know before starting a second of code what the data should look like before and after the test runs. So I write the test first. Now I could set up a mocked Statement, ResultSet and all that fun stuff but really that is a lot more work than creating the XML files for dbUnit and I'm going to have to set up all this data for integration tests. So why repeat myself.
I think the name used is not as important as the doing. Still if I had to pick a side, it would be "unit test".
I feel that testing against a database is important and should be done frequently. As it needs to be done frequently it should be quick to set up and execute. Now setting up a database may sound like work, but if all developers have access to a dedicated database that sits either on the local machine or on a decent sized box in the background and the dataset are restricted to use what is reliant to the test then this take little time to connect to and set up.
As I'm a lazy git I don't really want to be using different technologies for different sets of tests. Any test that wants to run frequently and is fast to run just becomes a JUnit test.
So finally when should I write it? Well I know before starting a second of code what the data should look like before and after the test runs. So I write the test first. Now I could set up a mocked Statement, ResultSet and all that fun stuff but really that is a lot more work than creating the XML files for dbUnit and I'm going to have to set up all this data for integration tests. So why repeat myself.
I think the name used is not as important as the doing. Still if I had to pick a side, it would be "unit test".
Subscribe to:
Posts (Atom)
