Mocking – What is it?

As many of you know, we have a couple of interns at our office this summer.  These guys (yes, they are all guys) have never done any testing before (they are in high school still) and I am rather passionate about testing my code.  So, being a good mentor (ok…so being a selfish person who knows that maintaining the software will fall to me and my team), I suggested that they learn about unit testing and begin applying it to the code they are writing.

As part of their learnings, the interns needed to learn about mock objects, what they are and why you need them.

What is a Mock?

Simply put, a mock object is a faked out version of an object.  You have complete control over what values are returned, and can interrogate it to see what values were passed into it.

Why would we want to do that?!

When writing unit tests, we should be constraining our tests to one method and one path through that method.  But, we know that when we are writing code, often our objects and methods need to access other objects and methods.  This leaves us in a conundrum.  How do we isolate our code?

Here’s a simple example.  Let’s say we have an object that can translate from several languages into English:

public class TranslatorFacade {
  private Translator klingonTranslator;
  private Translator spanishTranslator;

  public TranslatorFacade(Translator klingon, Translator spanish) {
    klingonTranslator = klingon;
    spanishTranslator = spanish;
  }

  public String translateFromKlingon(String phrase) {
    return klingonTranslator.translate(phrase);
  }
  public String translateFromSpanish(String phrase)...

In this example, we are creating a simple Facade that can call a bunch of different translators, but we are using the translator object directly.  We already have tests around each translator, so we don’t want to retest the translator here, but we want to make sure our facade is calling the right methods and is returning the right things.

How do we avoid retesting each translator then?  By mocking out the translators, of course!

Let’s give a short snippet of what that might look like if we wrote our own mock objects.  First, let’s assume we have an interface for translators which looks like this:

public interface Translator {
   public String translate(String phrase);
}

Then, in our test we could do something like this:

private class TestTranslator implements Translator {
  private String translatePhrase;
  private String phraseToReturn;
  public String translate(String phrase) {
    this.translatePhrase = phrase;
    return phraseToReturn;
  }
  public String translate_phrase() {
    return translatePhrase;
  }
  public void translate_return(String phraseToReturn) {
    this.phraseToReturn = phraseToReturn;
  }
}

// WARNING!  I DO NOT KNOW KLINGON
public testTranslateFromKlingon() {
  Translator klingon = new TestTranslator();
  klingon.translate_return("HORRAY");
  TranslatorFacade facade = new TranslatorFacade(klingon, new TestTranslator());
  String english = facade.translateFromKlingon("KA PLA");
  assertEquals("KA PLA", klingon.translate_phrase());
  assertEquals("HORRAY", english);
}

I know there is a lot of code up there.  But what I am trying to show is that we can easily make fake versions of our translators to capture the values that were sent into the object, as well as control the values that were returned from it.

This keeps us from re-testing our implementations when we are using the class somewhere else, which means that when we introduce an error, we are directed very precisely to where the issue is, rather than to all of the classes that happen to be using the failing method.

Seems like a lot of work

The above example is very simplistic.  Imagine that we needed to do something extra with the value that was returned from the translator in our method.  Perhaps we need to censor it or quote it.  We want to make sure that our censoring code is working as we expected.  By introducing mock objects, we can be sure that we are testing just that by setting our return values to strings that contain words that need censoring as well as ones that do not without having to know or understand the implementation of the translator class.

Let me state that again…because I think it is important.  By mocking the objects we are using, we don’t have to know or understand the implementation of the objects we are using!  Think about how many libraries you use in your day to day coding.  Being able to test your code without knowing the details of the code you are using is a big deal!

Do I have to write my own mocks?

No.  In fact, there are a lot of frameworks out there that will help you create mocks very easily.  Mockito and PowerMock are two that come to mind off the top of my head, and I know that there are many more out there.

Mean teacher

At work, we just hired a couple of summer interns from the local high school.  It is my job to be their mentor and project manager.

Today we held our first estimation session, and after it was over I was aware that I had come off rather brusquely.  This is a personality trait that I am well aware of in myself and am working on.  I asked my colleague if he noticed it and said he did, but he is used to it.

So, I decided to apologize to the interns for my manner.  Their response:
“That’s ok.  We’ve had mean teachers before.”

Communication & Tone

I am part of a group of game masters who run events at conventions.  At one of the large game conventions, our group is allowed to break the rules somewhat.  Typically all board games go in area A, all role-playing games in area B and so on.  Since we have a large group that runs a variety of events and we run them back to back, we are allowed to have our own space and run all of our events there.

In the last couple of years one of our group has taken over as liaison between us and the convention.  He has been doing an incredible job, our relationship with the convention has improved tremendously.  A big reason for this is he understands the importance of tone.

Two examples

Example the first:
The Boss asks for a task breakdown for a project that is not yet well defined.

Response A:
I can’t get you that.  That project is not fleshed out!

Response B:
I can’t get you that, because the project is not defined well enough yet.  But, I can give you a high level idea of what broad-stroke things we will likely need to do.  It won’t be at a level where people can start working on it, but might be helpful for planning.

See the difference?  In both responses we are saying that we are unable to provide “The Boss” with what he/she is asking, but, in the response B, we are offering an alternative.  That little act shows that we are hearing the need and are willing to work with the other person.

Example the second:
The product owner suggests an enhancement and you see some problems that you will face down the road if you follow the path laid out.

Response A:
If we do that, then we will have to deal with issues A, B & C.

Response B:
If I understand correctly, we want to add this enhancement to allow customers to do x which they currently are doing manually.  With the current proposal, we may run into some issues.  Do you mind if I do a little research to see if there are alternative solutions that will allow us to achieve the same goal?

Again, in our second example, we are stating that there are issues with the current proposal, but we are offering to work with the other person to make sure their goals are met.

That was easy

Not so fast!  My contrived examples make it seem very easy, but in reality we need to check ourselves when we are in a conversation.  Emotions often get in the way and lead us to answer with response A.  We may very well want to help the other individual, but we are not expressing it to them, and they cannot read our minds.

The second example is especially problematic for software engineers used to working and speaking with other software engineers.  I know this is an issue I deal with.  I am used to pointing out issues we will face and having the rest of the team jump in with ideas to address the issues.  So much so, that I expect this same behavior no matter who I am speaking with.

We aren’t always going to have an alternate approach to suggest right then, but I think it is fair to ask for some time to do some research.

Where do I go from here?

Tone is important in all of our interactions, not just at work.  It takes a lot of self-awareness to notice when we are coming off with a negative tone.  But, with practice you can improve your communication skills, and come off as a winner instead of a whiner.