Java RSpec alternative

I simply adore RSpec in Ruby land 🙂 It helped me embrace TDD in the best manner possible – by not getting into my way. Doesn’t sound much but it feels great when TDD cycle is so fast and unobtrusive that one simple cannot help running the spec over and over again. I don’t know, for me it feels like “let’s run the specs once again, if nothing else than to see how fast they run”. Compulsive but I can’t help it 🙂

Anyway, I’ve been working on some Java projects these couple of weeks and wanted the same TDD comfort zone as I get with RSpec. And a combination of Mockito, JUnit and PowerMock seems to be doing the trick. How about some code?:

public final class Blender {
  // ...
}

public class CreateYummyShake {
  private Blender blender;

  public CreateYummyShake(Blender blender) {
    // ...
    this.blender = blender;
  }

  public Shake with(List fruit) {
    return mix(takeRipe(fruit));
  }

  private Shake mix(List fruit) {
    // mix the fruit using blender
    // put it in glass
    // ...
  }

  protected List takeRipe(List Fruit) {
    new FilterFruit(fruit).takeRipe();
  }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest({Blender.class})
public class CreateYummyShakeTest {
  private Blender blender;

  @Before
  public void setup() {
    fruit = new ArrayList();
    fruit.add(mock(Fruit.class));
    fruit.add(mock(Fruit.class));
    blender = PowerMockito.mock(Blender.class); // mock final class with PowerMockito
    subject = spy(new CreateYummyShake(blender)); // spy the subject of the test, we need this later
  }

  @Test
  public void createsYummyShake() {
    doReturn(ripeFruit).when(subject).takeRipe(anyCollectionOf(Fruit.class)); // intercept call to another use case, no need to test this since it has it's own test
    when(blender.blend(fruit)).thenReturn(...); // use PowerMockito mock as you would use a Mockito one
    assertArrayEquals(ripeFruit.toArray(), subject.with(allFruit).ingredients.toArray());
  }
}

Before I explain this, a quick disclaimer: this code is nowhere near perfect or even nice, but hopefully it server the purpose of exposing some details about the test tools used. Consider yourself warned 🙂

Anyway, as you can see, Mockito plays well with collaborators and other use cases in the code. However, it can’t mock final classes (and some other combinations too, but you can look it up if need be). That’s where PowerMock comes in. It does the job, and as a bonus it lets you use those mock with Mockito as if nothing changed.

Also, subject under test might be using some other collaborator (ripe fruit filter in this case) and have a hard connection to it. Now, usually this would be injectable and easily mocked in test, but for the sake of argument, how does one test this? By extracting access to that collaborator to a protected method and stubbing it’s result. Mockito offers the ability to spy the subject under test. This way, the extracted access method can be mocked and the test is simplified. A separate test for the collaborator should exist of course.

The rest of Mockito DSL and options is pretty nice. It it not as pleasant as RSpec but it comes pretty close. I’ve always liked how RSpec tests read like prose, and this comes pretty close. The only issue I have is with asserts, but that can’t be helped unless JRuby is used, but that’s another story altogether.

Lastly, if you use Maven, you need these dependencies:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.10</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-all</artifactId>
  <version>1.9.5</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-module-junit4</artifactId>
  <version>1.5</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-api-mockito</artifactId>
  <version>1.5</version>
  <scope>test</scope>
</dependency>
Tagged , , , ,

4 thoughts on “Java RSpec alternative

  1. marcoss says:

    Constructive feedback:

    Line 5: strange that you would name a class with a verb. Wouldn’t it be more natural to have a YummyShake class (with a “create” method perhaps)? If you agree, I would also change method “with” to “addIngredient” or “mixWith”.
    Line 39: I assume that you want to create a spy on CreateYummyShake and not on CreateYummyShakeTest, correct?

    Thank you for the post!

    • elvanja says:

      Hi, thanks for the feedback!

      For line 39, yes, you’re spot on, should have been CreateYummyShake. Corrected in the post.

      As for the naming thingy, this is something I am playing around with. CreateYummyShake is supposed to be a use case. Anyway, the convention would be:
      * class name – the name of the use case, e.g. what it does, hence the verb
      * constructor – inject all the dependencies
      * execution method – “call” would be some kind of default, but I’ve found “with” to be nice, especially if has parameters

      Hence, CreateYummyShake is what I’d actually use in plain language, when explaining to someone what it does. I can always call it CreateYummyShakeUseCase, but that seems even sillier. There was an idea to use CreateYummyShakeContext or similar (see http://mikepackdev.com/blog_posts/24-the-right-way-to-code-dci-in-ruby), but in most projects this also seemed too much.

      Anyway, don’t hate me for it 🙂

Leave a comment