Pupils weren't dilated. He had blood in his mouth, and it looked like he'd bitten his tongue. The back of his head was bloody. His heart rate was elevated, and his breathing was ragged -- it sounded like his tongue was rattling in the back of his throat every time he breathed. It looked like he'd just been walking down the street, bit his tongue really hard and then fell straight back onto the pavement.
He started to move around a little bit after four minutes, and after five could say 'police' and 'wanna get up'. I didn't think it was a good idea for him to move until the paramedics came by, but I wasn't going to hold him down either. It turned out he couldn't really get up by himself, so we supported him until the paramedics came by.
I'm very glad he didn't stop breathing. I was not looking forward to giving him the breath of life.
An hour later, we successfully contested a parking ticket before a hearing officer.
This breaks down to the following stages:
Setup the object under test with any required mocks.
Expect some methods on the mock to be called.
Replay the mock once all the expectations have been made.
Execute the object's method when under test.
Verify the mock has had all its expectations met.
Assert the output of the method.
This basic framework takes care of most of the grunt unit tests.
But there's more to mocking than that. There's one particular gotcha I know about with EasyMock, and then there's the horrible, nasty, no-good edge cases that you run into. Let's start off.
Custom Argument Matching with Multiple Parameters
Let's start off with the gotcha first. Say you've got a method like the following:
List
Say that you want to match year, but not color. You can't say:
expect(carService.findCarsByYearAndColor(year, anyObject()).andReturn(null);
If you want to apply a custom argument matcher to either argument, you must apply it to both. So instead, you need to do this:
expect(carService.findCarsByYearAndColor(same(year), anyObject()).andReturn(null);
This is why same() exists.
Static and Final Methods
EasyMock does not allow you to mock static or final methods. EasyMock ClassExtension does not allow you to mock private methods or static classes. You can argue that such things should not exist, but we live an imperfect world where people don't always think of our needs.
This means that dealing with final classes like java.net.URL or java.io.File are fiddly. But not impossible. There's more than one way to skin this particular cat.
The by hand way is to use reflection: "final" is not final anymore. Heinz demonstrates how you can change final fields through several different versions of the JVM. This is a somewhat disturbing read, as it plays merry hell with my conception of what should and shouldn't be possible in Java. But it's there if you need it.
The snazzy way is to use JMockit, which is a small toolkit specifically designed to subvert the JVM. jMockit depends on the java.lang.instrument library, which is only available in JDK 1.5, but it provides functionality you can't find anywhere else.
The alternative method is to say "if your code is hard to test, then your code is badly written." While there may be a correlation, I think that what is 'badly written code' can only really be accurately be judged by a human being.
Private, Default or Protected Methods
jMockit is all over this.
Native methods
Don't know.
Static or Final Classes
This is handled as above by reflection, or by jMockit.
Inner Classes
Don't know. I suspect that anonymous inner classes are very tough. I believe that static inner classes should be accessible through jMockit, but haven't checked.
Constructors
EasyMock 2.3 allows you to define a partial mock that will call a specified constructor. That's good if you have something that needs to be passed into the object under test. So you can do:
If the object under testing needs to have a constructor mocked out, i.e.
Then jMockit will replace non-default constructors. I don't know of anything that will replace a default constructor.
Enums
As far as I can tell, there is no facility in EasyMock, EasyMock ClassExtension to mock out enum logic, as it is defined as final by the JVM. jMockit should be used here.
And that's it. jMockit looks like it's branched out into integration tests as well, notably Hibernate. I know that Unitils is a competitor here, but haven't played with either of them that much.
public static abstract class A {
public String s;
protected A(String s) {
this.s = s;
}
protected abstract int someMethod();
}
public void testFoo()
{
Constructor> cstr = A.class.getDeclaredConstructor(String.class);
ConstructorArgs constructorArgs = new ConstructorArgs(cstr, "test");
A a = createMock(A.class, constructorArgs, new Method[0]);
foo.setA(a);
expect(a.someMethod()).andReturn(0);
replay(a);
foo.execute();
}public class Foo
{
public Foo() { new File("c:\\boot.ini").delete() }
public void methodToTest() { }
}
I looked some other online systems, but Toodledo was the only one that had both state (well, folders) AND context. Since Toodledo is a web based task system was that I'd be unable to add to it when I wasn't in front of a computer. However, with the integrations to Twitter and Jott, I can SMS or even phone up and leave messages.
Once I found out there was an API as well, it was really only a matter of time before I'd find myself writing an adapter for it. And a command line client, in case you want to access it from a shell.
So here's my first Ruby gem.
If you're on a mac, you should be able to type 'sudo gem install toodledo' and then 'toodledo setup' and that should walk you through most of it.
It turns out that ActiveRecord does the same thing that Hibernate does and uses an internal proxy. So if you want a post containing a single image as an association, do this:
# Create a single image.
image = flexmock(:model, Image) { |mock|
mock.should_receive(:url).and_return('/post/10/blah.jpg')
mock.should_receive(:name).and_return('Blah Description')
}
# It's an association proxy pretending to be an array.
images = flexmock(ActiveRecord::Associations::HasManyAssociation) { |mock|
mock.should_receive(:find_by_name).and_return(image)
}
# The post itself.
post = flexmock(:model, Post) { |mock|
mock.should_receive(:object_id).and_return('10')
mock.should_receive(:images).and_return(images)
}This is a Law of Demeter violation, so the better solution may be to have a get_images method.
More info here:
Misunderstanding the Law of Demeter
Demeter's Revenger
Loose Coupling takes Tight Logic
As far as I understand it:
1) An integration test is one where the test code goes outside the realm of the class and has a dependency on an external entity.
2) Databases are external entities.
3) Fixtures will write to the test database.
Therefore:
Any test containing a fixture is an integration test, even if it's in test/unit and extends Test::Unit::TestCase.
Furthermore:
Unit tests are tests that can be run in isolation, in any order, without any external dependencies.
Whew. Had to get that out of my system.
Not that I don't understand the rationale; or that using fixtures could be extremely handy. But a spade is a spade.
As usual, as soon as I realized the underlying issue, there was no shortage of help, Jay Fields being the most helpful.