BlogtimeException

8th incarnation

Stubbing java.util.Calendar in Grails Test Cases, the Bad Parts

| Comments

After a happy couple of weeks, the method I had written about here started to fall apart, at least in acceptance tests.

The issue was that in some acceptance tests, the Geb framework was using java.util.Calendar internally, and now as the Calendar was stubbed globally, it wasn’t working correctly anymore.

Thankfully, this issue was easily solved with a layer of redirection: I modified my code to use a “utils” class to access Calendar, and then when need be I stubbed the utils class instead.

DateUtils
1
2
3
4
5
6
class DateUtils {
  boolean isTodayMonday() {
      def cal = Calendar.getInstance()
      return cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY
  }
}
Stubbing DateUtils to always return true when isTodayMonday is called
1
DateUtils.metaClass.static.isTodayMonday = { Calendar.MONDAY }

Geb Navigator.text() Issues

| Comments

Wasted a couple of hours today on debugging a Geb issue: Navigator.text() was not working as expected.

According to the API docs, it “Returns the text content of the first context element”, but it was returning an empty string for me, even though it was matching an element that had some text within.

In the end, it turned out Navigator.text() returns an empty string if the element it matches is hidden (e.g. it has a display:none CSS style).

Stubbing java.util.Calendar in Grails Test Cases

| Comments

Sometime ago at work I needed to unit-test a Groovy class that was using java.util.Calendar in method-local scope. The SUT (system under test) was similar to the following DateUtils class:

1
2
3
4
5
6
7
class DateUtils {
    static def isTodayMonday() {
        Calendar now = Calendar.getInstance()
        int currentDayOfWeek = now.get(Calendar.DAY_OF_WEEK)
        return Calendar.MONDAY == currentDayOfWeek
    }
}

In order to unit-test DateUtils.isTodayMonday(), we need two test cases:

  1. A test case that demonstrates that isTodayMonday() returns true if java.util.Calendar returns Calendar.MONDAY as the current day of week, and
  2. A test case that demonstrates that isTodayMonday() returns false if java.util.Calendar returns anything other than Calendar.MONDAY as the current day of week.

As you know, it is not easy to stub Calendar.getInstance() and Calendar.get(int) in Java when they are used like this. However in Groovy maps can be coerced into classes at runtime and this simplifies writing our unit test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
void isTodayMondayShouldReturnTrueIfTodayIsMonday() {
    // Create a calendar stub that always returns MONDAY for the current day of week
    def stubCalendar = [get: { int field -> Calendar.MONDAY}] as Calendar;

    // Override Calendar.getInstance() so that it always returns our calendar stub
    Calendar.metaClass.static.getInstance = { stubCalendar }

    assert DateUtils.isTodayMonday()
}

@Test
void isTodayMondayShouldReturnFalseIfTodayIsNotMonday() {
    // Create a calendar stub that does not return MONDAY, (e.g. returns TUESDAY) for the current day of week
    def stubCalendar = [get: { int field -> Calendar.TUESDAY}] as Calendar;

    // Override Calendar.getInstance() so that it always returns our calendar stub
    Calendar.metaClass.static.getInstance = { stubCalendar }

    assert DateUtils.isTodayMonday() == false
}

In a later post I’ll explain why I prefer this approach over using Grails’ built-in StubFor.

Note: I have simplified this unit test by not testing for all days of the week. Otherwise in a more rigorous test suite, one would probably write one test case per each day of the week.

Agile, an Over(ab)used Term

| Comments

Earlier today I was thinking about the overuse of the term “agile” in the industry and how disturbing and distractive it is. Then, now at night, I stumbled upon this:

DI frameworks are unnecessary. In more rigid environments, they have value. In agile environments like Ruby, not so much. The patterns themselves may still be applicable, but beware of falling into the trap of thinking you need a special tool for everything. Ruby is Play-Doh, remember! Let’s keep it that way.

Dude! Ruby is not an agile environment! Ruby is only a dynamically typed language just like JavaScript, LISP, and what not. Let’s keep it that way! Stop abusing “agile”.

This also reminded me about this fascinating story about Steve Jobs and overuse of the Apple logo in Mac OS menus:

There are too many Apples on the screen! It’s ridiculous! We’re taking the Apple logo in vain! We’ve got to stop doing that!

Now I am not an agile zealot of any sorts, but if you are, if you care about it, and if you believe in it, then stop over(ab)using it.

Ruby’s Optional Method Parentheses

| Comments

While it leads to good looking and readable DSLs, as there’s not a strict rule for when to use parentheses and when not to, it adds another type of coding style inconsistency to code written by a team of programmers.