EasyMock, Unitils and a mixture of both

So, we do use unitils and easymock for quite a while now. We do our mocking with easymock and use the unitils-inject and unitils-easymock modules to simplify our tests.

But, there was a very weird behaviour. So I tried to boil it down to the reason why it fails. Here is some code that we actually want to test:

package de.matthiascoy.easymock.easymockprimitivetest;
public interface InterfaceB {
    void foobar(boolean b);
}
package de.matthiascoy.easymock.easymockprimitivetest;
public class TestedObjectClass {
    private InterfaceB interfaceB;
    public void runMe(boolean b) {
        interfaceB.foobar(b);
        interfaceB.foobar(b);
    }
}

So, obviously we want to test toe runMe-method and want to verify that the two calls on the interfaceB are actually done with the given arguments. Our first try was this code:

package de.matthiascoy.easymock.easymockprimitivetest;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.unitils.UnitilsJUnit4TestClassRunner;
import org.unitils.easymock.EasyMockUnitils;
import org.unitils.inject.annotation.InjectIntoByType;
import org.unitils.inject.annotation.TestedObject;

@RunWith(UnitilsJUnit4TestClassRunner.class)
public class EasyMockAndUnitilsTest {

    @TestedObject
    private TestedObjectClass testedObject;

    @InjectIntoByType
    private InterfaceB interfaceB;

    @Before
    public void setUp() {
        this.interfaceB = EasyMock.createMock(InterfaceB.class);
    }

    @Test(expected = AssertionError.class)
    public void testPrimitiveBoolean() {
        boolean B = true;

        interfaceB.foobar(B);
        EasyMock.expectLastCall();
        interfaceB.foobar(!B);
        EasyMock.expectLastCall();
        EasyMockUnitils.replay();

        testedObject.runMe(B);

        EasyMockUnitils.verify();
    }
}

What you can see is, that we do expect first TRUE and then FALSE, but that should fail. We do test that with the „expected=AssertionError“ value in the @Test annotation. But actually this tests fails, because there is no AssertionError. With just a „@Test“ the test just runs and shows us a green light. That’s very strange. So, we thought: must be a bug in the testingframework, but which one?

So, we created a EasyMock 3.2 only test

package de.matthiascoy.easymock.easymockprimitivetest;

import org.easymock.EasyMock;
import org.easymock.EasyMockRunner;
import org.easymock.EasyMockSupport;

import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(EasyMockRunner.class)
public class PureEasyMockTest extends EasyMockSupport {

    @TestSubject
    private TestedObjectClass testedObject = new TestedObjectClass();

    @Mock
    private InterfaceB interfaceBMock;

    @Test(expected = AssertionError.class)
    public void testPrimitiveBoolean() {
        boolean B = true;

        interfaceBMock.foobar(B);
        EasyMock.expectLastCall();
        interfaceBMock.foobar(!B);
        EasyMock.expectLastCall();

        replayAll();

        testedObject.runMe(B);

        verifyAll();
    }

    @Test(expected = AssertionError.class)
    public void testPrimitiveBooleanWithEq() {
        boolean B = true;

        interfaceBMock.foobar(EasyMock.eq(B));
        EasyMock.expectLastCall();
        interfaceBMock.foobar(EasyMock.eq(!B));
        EasyMock.expectLastCall();

        replayAll();

        testedObject.runMe(B);

        verifyAll();
    }
}

This test does work. So, easymock seems not to be the problem. Now, to unitils:

package de.matthiascoy.easymock.easymockprimitivetest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.unitils.UnitilsJUnit4TestClassRunner;
import org.unitils.inject.annotation.InjectIntoByType;
import org.unitils.inject.annotation.TestedObject;
import org.unitils.mock.Mock;

@RunWith(UnitilsJUnit4TestClassRunner.class)
public class UnitilsTest {

    @TestedObject
    private TestedObjectClass testedObject;

    @InjectIntoByType
    private Mock<InterfaceB> interfaceB;

    @Test(expected = AssertionError.class)
    public void testPrimitiveBoolean() {
        boolean B = true;

        testedObject.runMe(B);

        interfaceB.assertInvoked().foobar(B);
        interfaceB.assertInvoked().foobar(!B);
    }
}

And this test just works fine as well. So, the problem must be somewhere in the middle. I’m still not sure where exactly, but the second call to interfaceB.foobar in EasyMockAndUnitilsTest.testPrimitiveBoolean does not care about the arguments. It does care about if it’s called or not, but the argument is ignored.

So, we decided to migrate all our tests to pure easymock. Maybe, somehow we will move to mockito at the end … maybe.

ant + bad version

Ich  hatte die ganze Zeit ein Problem, dass wenn ich mein JAVA_HOME auf java5 gebogen habe, dass sich ant verabschiedet hat mit

java.lang.UnsupportedClassVersionError: Bad version number in .class file

Also noch bevor ĂĽberhaupt das build.xml ins Spiel kam. Nach ein bissle recherche liegt es daran, das die xerces-XML-lib in ubuntu ohne target gebaut ist und somit auf 1.6 steht. Das klappt dann natĂĽrlich nicht mit 1.5.

Der Fix den ich jetzt gemacht habe ist relativ trivial:

http://packages.ubuntu.com/de/quantal/all/libxerces2-java/download

dort, eigentlich vor seiner Zeit (Quantal ist ja noch nicht stable) wurde das target wieder auf 1.4 gesetzt und somit klappts auch mit den Nachbarn.

Geburtstage

Inzwischen hab ich eine einigermassen gepflegte Kontaktliste, Google Contacts sei Dank. FrĂĽher hatte ich ein kleines Skript das ĂĽber meine Datenbank gegangen ist und die heutigen und morgigen Geburtstage rausgesucht hat und per E-Mail verschickt hat. Hier mal die Version fĂĽr Google Contacts/Calendar:

#!/bin/bash
TODAY=$(date +%Y-%m-%d) # 2010-03-30
TOMORROW=$(date --date=tomorrow +%Y-%m-%d)

TODAY2=$(echo ${TODAY} | cut -d "-" -f 2,3 )
TOMORROW2=$(echo ${TOMORROW} | cut -d "-" -f 2,3 )

YEAR=$(echo ${TODAY} | cut -d "-" -f 1 )
FOUND="false"

google calendar list --cal '.*birthday.*' --date ${TODAY},${TOMORROW} --field title | grep "^[^[]" | sed -e "s/'s birthday//g" > /tmp/file.txt
while read line; do
  LASTNAME=$(echo $line | rev | cut -d " " -f 1 | rev)
  BIRTHDAY=$(google contacts list "$LASTNAME" --fields birthday | grep "${TODAY2}\|${TOMORROW2}")
  if [ "${BIRTHDAY}" != "" ]; then
    BIRTHYEAR=$(echo ${BIRTHDAY} | cut -d "-" -f 1)
    echo "${line}: ${BIRTHDAY} -> $(( ${YEAR} - ${BIRTHYEAR} )). Geburtstag"
    FOUND="true"
  fi
done < /tmp/file.txt

if [ "${FOUND}" == "false" ]; then
  echo "no birthdays"
fi

rm /tmp/file.txt

Potthässlich, aber funktional. Man braucht dafür zwei Dinge

  1. https://code.google.com/p/googlecl/
  2. http://www.google.com/support/calendar/bin/answer.py?hl=en&answer=37098 -> More -> „Contacts‘ birthdays and events“

Wird bei mir per Cronjob aufgerufen und produziert dann beispielsweise sowas:

Peter Test: 1981-11-05 -> 29. Geburtstag
Karlheinz Mustermann: 2009-11-06 -> 1. Geburtstag