Dahlia Bock

21Aug/090

Mocking: Mockito vs EasyMock example

Ever since I was introduced to Mockito about a year ago, I've been a big fan. I wrote a couple of posts about it and promised a long, long time ago that I would post an example of a test written in Mockito and one in another mocking framework. The lucky chosen one was EasyMock. My biggest plugs for Mockito would be:

  1. Test readability. Mockito tests are more concise and it discourages noise in test code.
  2. The ability to clearly distinguish test expectations from test verifications so that you know what exactly you're stubbing and what you're testing.

Here's an example of a class that I want to test: ProfileService.java. NOTE: Please ignore the design of the code itself. Let's just say that all I wanted to do was to test it's behavior without changing it. And I do know that it's not the best, in fact far from the best.

There is one method in that class which retrieves a Profile from the database and finds all the contacts associated with that profile and goes through all of them and if there is an application in a contact that is already Closed, an exception is thrown and I'm not allowed to close the profile. Otherwise, the status of the profile is changed to Closed and this is updated in the database through the repository.

ProfileService.java

Let's look at the EasyMock test first.

ProfileServiceTestWithEasyMock.java

Notice that test verifications, i.e. that profileRepository.updateProfile() was called at the end, are interchanged with test expectations, thus blurring the line between what you're setting up and what you're testing.

Now let's check out the Mockito version of the test.

ProfileServiceTestWithMockito.java

First thing you should notice is that the test is much shorter, yes, only by a few lines, but it's a few lines less confusing. The test is also easier to break into a logical given-when-then BDD-style scenario. There is also clear distinction between what you're stubbing (expectations and setup) and what you're actually testing (verifications).

I can't see how EasyMock promotes cleaner and clearer tests, I really can't.

20Aug/091

Test Driven Development – 10 years later

Michael Feathers and Steve Freeman have a really good video talking about the phases TDD went through over the last few years. I just want to highlight the summary of their presentation.

  1. Professionals test their code.
    And when they say 'test', I truly believe they mean writing automated tests. Nothing manual.
  2. Separate what from how.
    What you're testing should be set apart from how you're testing it. For example, my colleague Mark recently spoke a little about how setting up a test correctly can sometimes turn into noise and reduce the readability of your tests. One way to avoid the noise is to use Builders.
  3. Automatic tests confirm features.
    I've heard people say things like, "I had to go back and test some of the features from last iteration because something broke this iteration". If we had a suite of automated tests (be it functional, integration or unit), we could avoid situations like that.
  4. It's a change in culture.
    And it still is, surprisingly. Even after test years, TDD is still a lesser known truth in some organizations. Heck, even the understanding of what a unit test is in shockingly lacking.
  5. "Working" isn't good enough.
    A lot of times we say things like "I tested the code, and it's working." So what exactly does 'working' mean? Does it conform to the business' expectations? Does it perform well? Another colleague of mine, Phil, wrote about the 3 Things Agile Teams Should Care About - what does it mean to be done?. Let's forget about being Agile for a moment and just focus on getting a particular functionality working the way as the business expected consistently.
  6. Listen to the tests.
    What should you do if the tests are failing when you run the build? What should you do when the tests fail on the continuous integration build? We should listen to them. Tests are a feedback mechanism. They ensure the integrity of our system and we need to make sure that we pay attention to them at all times.
  7. A working system provides feedback.
  8. Focus on intent.
    What is the intent of the test that you're writing? Is it expressed clearly in the method name? Are we just testing getters and setters or are we testing the behavior of the code?
  9. When you're lost, slow down.
  10. It's not only about testing.
  11. Legacy code is code without tests.
  12. Understand the principles behind the practices.
    Agile advocates individuals and interactions over processes and tools. Behind every practice is an intent. We should understand the intent first instead of blindly following the practice lest we fall into the trap of using a practice for a sake of using it.
Filed under: agile, tdd, testing 1 Comment
6Aug/092

Why I think layer teams are a bad idea

So what exactly do I mean by 'layer teams'? I mean structuring your software development team in such a way that you have a group of developers for each layer (or more), e.g. UI, services, database, etc. So a UI developer is only concerned about one specific part of the application, namely the UI, obviously, and the Services developer with the services, and so on and so forth.

Problems that I've seen surfacing from such a setup:

  1. There's an enormous amount of overhead time spent going back and forth between the different groups when defining interfaces. Maybe it's the nature of the teams I've worked with in the past but IMHO this extra time could be spent writing tests that iron out the interactions between the layers.
  2. Then there's another chunk of time spent putting those pieces together and making sure they work correctly, i.e. integration.
  3. This causes silos in the development team where only some people know about the UI, others about the back-end services, etc. This discourages developers to step outside their comfort zone to learn another person's 'trade'.
  4. Update >>> Introducing specialized teams also increases the amount of distrust between the teams. One example is the database management team holding on to the schema and data for dear life and believing that no developer should have access to change it. Maybe this is common situation across a lot of projects regardless of team setup, but separating the team does decrease their level of trust for each other.

What I think is better is to have every developer comfortable with every part of the application, even if it means taking a productivity hit - as I've heard it being said. Let's say I have a story on the wall that says: "Add item to shopping cart". Ideally, a pair of developers would start first by working with the QA to define acceptance criteria and writing the acceptance tests for that feature. (This is a side note to a session at Agile 2009 that I'm very interested in: Where Does Developer Testing End and Tester Testing Begin?. I wish I was able to go.) Then they would implement what is needed to be able to click through on the application to add an item to the shopping cart which eventually ends up in the database.