samedi 2 août 2014

Develop and test a Node.js HTTP client

Call an external HTTP service is a very common task when we develop a Node.js application. In production, an external service can be instable and it is essential that this instability does not broke your application. Whatever the project or the external service, cases to take into account are always the same.

From a simple use case, we will see in this article what are the different steps to follow in order to create a robust HTTP client in Node.js.

Our example

Our goal is to create a method countEmployees returning the result of the following HTTP request :

GET http://localhost:3000/employees/count
{"count":1200}

Step 1 : nominal case


In this step, we will write a first implementation of our client and test the case where the external service responds correctly.

To begin, using mocha, let's create a test which verifies that the value returned by the client is directly the value returned by the external service.

describe('employees count service', function() {
  it('should return 1200', function() {
 
    client.countEmployees().then(function(count) {
      count.should.equal(1200);
    }).done();
  });
});

Then, write a first implementation of the countEmployees method :

var Q = require('Q'),
  request = require('request'),
  config = require('./config');

exports.countEmployees = function() {
  var deferred = Q.defer();

  var options = {
    url: config.employeeCountUrl,
    json: true
  };

  request(options, function (error, response, body) {
    var employeesCount = body.count;
    deferred.resolve(employeesCount);
  });

  return deferred.promise;
};

We use in this implementation two modules : request for the HTTP requests and Q for the promises.

Here our test do a real HTTP call to the external service. To make the test pass, the HTTP service must be available and always return the same value. So it becomes essential to simulate this service. To do that, we will use nock module which allows to mock HTTP access in Node.js.

Starting with nock is easy thanks to its recorder. Firstly let's add the following instruction in our test :

beforeEach(function() {
  nock.recorder.rec();
});

During the test execution, we discover these lines in the console :

<<<<<<-- cut here -->>>>>>
nock('http://localhost:3000')
  .get('/employees/count')
  .reply(200, {"count":1200}, { 'x-powered-by': 'Express', 'content-type': 'application/json; 
charset=utf-8', 'content-length': '14', etag: 'W/"e-2043423703"', date: 'Wed, 09 Jul 2014 20:59:20 GMT',
connection: 'keep-alive' });
<<<<<<-- cut here -->>>>>>

You just have to copy past these lines in your test to simulate the execution of the request http://localhost:3000/employees/count. Don't hesitate to clean what you don't need, like for example the response header.

Another useful nock instruction is this one : nock.disableNetConnect() which allows to forbid all HTTP access. Our test becomes :

describe('employees count service', function() {
  beforeEach(function() {
    nock.disableNetConnect();
  });
 
  it('should return employees count', function() {
    nock('http://localhost:3000')
      .get('/employees/count')
      .reply(200, {count:1986});
 
    client.countEmployees().then(function(count) {
      count.should.equal(1986);
    }).done();
  });
});

And now, when the client executes the request, it is not the service which answers but nock. Moreover, we have the guarantee that we don't do extra HTTP requests. Now, shutdown the HTTP service and relaunch the test : it passes !

Our first goal is reached : we have a first implementation of our client and a test covering the nominal case.

Step 2 : service in error


Using nock, it is now easy to test the error cases. In this second step, we want to handle the case where the service returns an HTTP error. Let's add a new test and simulate the case where the service returns an error 500.

it('should return an error if http service is in error', function(done) {
  nock('http://localhost:3000')
    .get('/employees/count')
    .reply(500, {});
 
  client.countEmployees().then(function(count) {
    done(new Error('method should return an error'));
  }).catch(function() {
    done();
  });
});

The test doesn't pass. Indeed, the client doesn't return an error but a null result. Don't panic, we can easily handle this case and return an error if the http status code is not in the 200 range :

if (response.statusCode >= 300) {
  deferred.reject(new Error('Service has an invalid status code : ' + response.statusCode));
}

Step 2 goal is reached : our client can now handle HTTP errors.

Step 3 : service returns unexpected data


In this third step, we want to check that the client works correctly if the service returns unexpected data. In a new test, we will simulate that the service returns no count field but another field. With nock again, it is easy :

whenEmployeesCountIsCalled().reply(200, {nb:1986});

Please note that we factorized the nock call with the following method :

var whenEmployeesCountIsCalled = function() {
  return nock('http://localhost:3000')
    .get('/employees/count');
};

The test fails. To fix it, you can test that the expected field is in the HTTP request :

if (!employeesCount) {
  deferred.reject(new Error('Service did not return employees count'));
}

Step 3 goal is reached : we know how to handle unexpected data.

Step 4 : service is slow


In this step, we want to test the case where the external service is too slow. We can also do that with nock :

whenEmployeesCountIsCalled()
  .delayConnection(1500)
  .reply(200, {count:1986});

DelayConnection instruction allows to delay the HTTP answer of 1500 ms. Here we want that our service interrupts the connection after, for example 500 ms. With request module, you can configure a timeout :

var options = {
  url: config.employeeCountUrl,
  json: true,
  timeout: 500
};

Then you have to test if the error object is defined :

if (error) {
  deferred.reject(error);
  return;
}

The test passes. Step 4  is finished : our client is protected from slow access.

Step 5 : service is unavailable


In this last step, we want to check our client behavior with an unavailable service. Current version of nock cannot help to test this case. However we just need to do a real HTTP access on an unexisting host :

it('should return an error if service is unavailable', function(done) {
  client = rewire('../client/employees.client');
  client.__set__('config', {
    configEmployeeCountUrl: 'http://doesnotexist.localhost:3000/employees/count'
  });
 
  client.countEmployees().then(function() {
    done(new Error('method should return an error'));
  }).catch(function() { 
    done();
  });
});

Here we use rewire module to override the config object and give an unexisting url. The test passes. Indeed the fix from step 4 allows also to handle this error. Our goal is reached, we finalized the implementation of our HTTP client !

Conclusion 

Unavailable, slow, broken... production hazards are large and it is important that your application stays stable in these cases. Thanks to nock, we can easily reproduced these errors and build a robust code.

We covered only a few features of nock. To go further, don't hesitate to read the full documentation here : https://github.com/pgte/nock.

To finish, you will find the complete code on the following github respository : https://github.com/jsebfranck/node-http-example.






Translated from a Xebia article I wrote (in french)

dimanche 9 mars 2014

Page Object pattern with CasperJS

In this article I will quickly introduce an UI test framework, CasperJS, and how we can improve UI tests maintainability using the Page Object Pattern. The goal is not to cover all CasperJS features but to show how to write maintainable tests.

CasperJS is an open source tool used to test your web application user interface. From javascript code, you can simulate in a test all possible users interactions with your interface. For example you can click on a link, fill and submit a form, and finally check your DOM elements.

To start, let's see a concrete example of a CasperJS test and after we will see how to refactor the written tests using the Page Object pattern.

Our example

We will test three pages of the spring travel application :
  • the login page
  • the hotels search page & bookings listing
  • and the hotels search result page

Login page

Hotels search page & bookings listing


Hotels search result page

For our first CasperJS test, we want to cover the following scenario :
  • the user fills and submits the login form
  • the user arrives on the bookings listing
  • the user can see his last bookings
Here is the CasperJS test :

casper.test.begin('When I connect myself I should see my bookings', function (test) {
  casper.start(casper.cli.options.baseUrl + '/login');

  casper.then(function () {
    test.assertExists('form[name="f"]', 'Is on login page');
  });

  casper.then(function () {
    this.fill('form[name="f"]', {
      'j_username': 'scott',
      'j_password': 'rochester'
      }, false);
  });

  casper.then(function () {
    this.click('form[name="f"] button[type="submit"]', 'Login submit button clicked');
  });

  casper.then(function () {
    test.assertUrlMatch('hotels/search', 'Is on search page');
    test.assertTextExists('Current Hotel Bookings', 'bookings title are displayed');
    test.assertExists('#bookings > table > tbody > tr', 'bookings are displayed');
  });

  casper.run(function () {
    test.done();
  });
});

As you can see this test is very fluent and easily readable. Some explanations :
  • casper.start starts the scenario on a given url
  • casper.then sections describe a specific user action or some assertions.
  • fill and click methods allow to simulate user actions
  • assertExists, assertUrlMatch and assertTestExists allow to check the DOM content
  • casper.cli.options.baseUrl allows to get a custom parameter passed on the casper js command line
Now let's cover a little bit more complex scenario in a new CasperJS test :
  • the user fills and submits the login form
  • the user arrives on the hotels search page
  • the user fills and submits the hotels search page
  • the user can see several hotels in Atlanta

casper.test.begin('When I connect myself and search hotels in Atlanta 
Then should find three hotels', function (test) {
  casper.start(casper.cli.options.baseUrl + '/login');

  casper.then(function () {
    test.assertExists('form[name="f"]', 'Is on login page');
  });

  casper.then(function () {
    this.fill('form[name="f"]', {
      'j_username': 'scott',
      'j_password': 'rochester'
      }, false);
  });

  casper.then(function () {
    this.click('form[name="f"] button[type="submit"]', 'Login submit button clicked');
  });

  casper.then(function () {
    test.assertUrlMatch('hotels/search', 'Is on search page');
  });

  casper.then(function () {
    this.fill('form[id="searchCriteria"]', {
      'searchString': 'Atlanta'
      }, false);
  });

  casper.then(function () {
    this.click('form[id="searchCriteria"] button[type="submit"]');
  });

  casper.then(function () {
    test.assertUrlMatch('hotels?searchString=Atlanta', 'Is on search result page');
    test.assertElementCount('#hotelResults > table > tbody > tr', 3, '3 hotels have been found');
  });

  casper.run(function () {
    test.done();
  });
});


Again the test is fluent and readable. But a lot of code has just been copy/paste and we have now several duplicated lines of code.

How can we factorize that? By creating some utils methods? Not exactly, it is here that comes the famous Page Object pattern!

Page Object pattern

Page Object pattern is described on Martin Fowler website.

Page Object pattern by Martin Fowler


The main ideas are :

The test must not manipulate directly the page UI elements. This manipulation must be done within a Page Object which represents an UI page or an UI page fragment. The Page Object makes a complete abstraction of the underlying UI and it becomes an API where it is possible to easily find and manipulate the page data.

This encapsulation has two benefits : the test logic is about user intentions and not about UI details, so it is easier to understand. Plus, if the UI is modified, this will affect only the Page Objects and not the tests.

Asynchronism behavior of the pages must also be hidden by the Page Object. It is a specific behavior of your UI and you don't want to make it appear in your tests.

For a single page, you can have several Page Objects if there are several significant elements on the page. For example you can have a Page Object for the header and one for the body.

Assertions responsibility can be in the Page Object or in the test. In the Page Object it helps avoid duplication of assertions in the tests, but the Page Object responsibility becomes more complicated as it is responsible to give access to the page data, plus to have the assertion logic.

This pattern can be apply for any UI technologies : HTML pages, java swing interfaces or others UI.

Now, let's use the Page Object pattern for our CasperJS tests.

CasperJS with Page Object pattern

In our test, we navigate through three pages, so we will create three Page Objects : LoginPage, SearchPage and SearchResultPage.

Our first page is the login page. Here we must be able to start the scenario on this page, to check that the page is correct, and to fill and submit the login form. We will do that with four methods : startOnLoginPage, checkPage, fillForm and submitForm. All of these methods are created in a LoginPage object in a LoginPage.js file :

function LoginPage() {

  this.startOnLoginPage = function () {
    casper.echo("base url is : " + casper.cli.options.baseUrl);
    casper.start(casper.cli.options.baseUrl + '/login');
  };

  this.checkPage = function () {
    casper.then(function () {
      casper.test.assertUrlMatch('login', 'Is on login page');
      casper.test.assertExists('form[name="f"]', 'Login page form has been found');
    });
  };

  this.fillForm = function (username, password) {
    casper.then(function () {
      this.fill('form[name="f"]', {
        'j_username': username,
        'j_password': password
      }, false);
    });
  };

  this.submitForm = function () {
    casper.then(function () {
      this.click('form[name="f"] button[type="submit"]', 'Login submit button clicked');
    });
  };
}

Now we need a page for the search. We need to check the page, to check that the user bookings are displayed, and to fill and submit the search form. We will do that on a SearchPage object in the file SearchPage.js :

function SearchPage() {

  this.checkPage = function () {
    casper.then(function () {
      casper.test.assertUrlMatch('hotels/search', 'Is on search page');
    });
  };

  this.checkThatBookingsAreDisplayed = function() {
    casper.then(function () {
      casper.test.assertTextExists('Current Hotel Bookings', 'bookings title are displayed');
      casper.test.assertExists('#bookings > table > tbody > tr', 'bookings are displayed');
    });
  };

  this.fillSearchForm = function(searchTerms) {
    casper.then(function () {
      this.fill('form[id="searchCriteria"]', {
        'searchString': searchTerms
        }, false);
    });
  };

  this.submitSearchForm = function() {
    casper.then(function () {
      this.click('form[id="searchCriteria"] button[type="submit"]');
    });
  };
}

Finally we need a Page Object for our SearchResultPage. Here we just want to check the page and to check that the results are correctly displayed :

function SearchResultPage() {

  this.checkPage = function () {
    casper.then(function () {
      casper.test.assertUrlMatch('hotels?searchString=', 'Is on search result page');
    });
  };

  this.checkThatResultsAreDisplayed = function(expectedCount) {
    casper.then(function () {
      casper.test.assertElementCount('#hotelResults > table > tbody > tr', expectedCount, expectedCount + ' hotels have been found');
    });
  };
}

Now we can use these three Page Objects in our test :

phantom.page.injectJs('LoginPage.js');
phantom.page.injectJs('SearchPage.js');
phantom.page.injectJs('SearchResultPage.js');

var loginPage = new LoginPage();
var searchPage = new SearchPage();
var searchResultPage = new SearchResultPage();

casper.test.begin('When I connect myself I should see my bookings', function (test) {
  loginPage.startOnLoginPage();
  loginPage.checkPage();
  loginPage.fillForm('scott', 'rochester');
  loginPage.submitForm();

  searchPage.checkPage();
  searchPage.checkThatBookingsAreDisplayed();

  casper.run(function () {
    test.done();
  });
});

casper.test.begin('When I connect myself and search hotels in Atlanta 
Then should find three hotels', function (test) {
  loginPage.startOnLoginPage();
  loginPage.checkPage();
  loginPage.fillForm('scott', 'rochester');
  loginPage.submitForm();

  searchPage.checkPage();
  searchPage.fillSearchForm('Atlanta');
  searchPage.submitSearchForm();

  searchResultPage.checkPage();
  searchResultPage.checkThatResultsAreDisplayed(3);

  casper.run(function () {
    test.done();
  });
});

Our two tests are now more readable and there is a complete abstraction of UI elements. If you modify your HTML code, you will easily identify which page to modify and you won't have impacts on your tests.

Variant n°1 : use four Page Objects

The search page provides the search form and the bookings listing. I choose to modelize that in a single Page Object. But another option is to create two Page Object : one for the search and one for the listing. The BookingListingPage.js is now :

function BookingListingPage() {

  this.checkPage = function () {
    casper.then(function () {
      casper.test.assertUrlMatch('hotels/search', 'Is on booking listing page');
    });
  };

  this.checkThatBookingsAreDisplayed = function() {
    casper.then(function () {
      casper.test.assertTextExists('Current Hotel Bookings', 'bookings title are displayed');
      casper.test.assertExists('#bookings > table > tbody > tr', 'bookings are displayed');
    });
  };
}

And our first test becomes :

casper.test.begin('When I connect myself I should see my bookings', function (test) {
  loginPage.startOnLoginPage();
  loginPage.checkPage();
  loginPage.fillForm('scott', 'rochester');
  loginPage.submitForm();

  bookingListingPage.checkPage();
  bookingListingPage.checkThatBookingsAreDisplayed();

  casper.run(function () {
    test.done();
  });
});

Variant n°2 : keep assertions in tests

I choose to write the assertions directly in the Page Objects. Thess objects have then two responsibilities : give an access to the page data and provide assertions. Martin Fowler recommends to distinguish these responsitilibies and to keep assertions in the test. In that case the Page Object provides only an accessor to the page element and it is the test responsibility to check its content. For example for the SearchResultPage Object, the method :

// test
searchResultPage.checkThatResultsAreDisplayed(3);

// page object
this.checkThatResultsAreDisplayed = function(expectedCount) {
    casper.then(function () {
      casper.test.assertElementCount('#hotelResults > table > tbody > tr', expectedCount, expectedCount + ' hotels have been found');
    });
  };

Becomes :

// test
casper.test.assertEquals(searchResultPage.getResultsCount(), 3, '3 hotels have been found');

// page object
  this.getResultsCount = function() {
    return casper.evaluate(function() {
      return __utils__.findAll('#hotelResults > table > tbody > tr').length;
    });
  };


Conclusion

When you code your features, you don’t hesitate to separate the different layers in different objects. It is exactly what the Page Object pattern recommend to do : separate the test logic from the UI layer. In this article I applied it to CasperJS tests but this pattern is also relevant with other tools like for example Selenium, ZombieJS or even Gatling.

Please find the complete code on my github repository about tests.
Please also find my CasperJS best practices here.

vendredi 17 janvier 2014

Unit tests and integration tests coverage in sonar with gradle

I recently needed to configure a multi-module gradle project in order to generate unit test, integration test and overall coverage indicators in sonar. As it wasn't so obvious I thought it would be a good idea to share my example.

The goal is to generate the following report in sonar :


Complete gradle file


So here is my complete build.gradle file :

apply plugin: 'sonar-runner'

allprojects {
  apply plugin: 'java'
  apply plugin: 'jacoco'

  sourceSets {
    integtest {
      java {
        compileClasspath += main.output
        runtimeClasspath += main.output
        srcDir 'src/integtest/java'
      }
    }
  }

  configurations {
    integtestCompile.extendsFrom testCompile
  }

  task "integtest"(type: Test, dependsOn: integtestClasses) {
    testClassesDir = sourceSets.integtest.output.classesDir
    classpath = sourceSets.integtest.runtimeClasspath

      jacoco {
          destinationFile = file("$buildDir/jacoco/jacocoIntegTest.exec")
      }
  }

  test {
    jacoco {
      destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
    }
  }

  sonarRunner {
    sonarProperties {
      property "sonar.jacoco.reportPath", "$buildDir/jacoco/jacocoTest.exec"
      property "sonar.jacoco.itReportPath", "$buildDir/jacoco/jacocoIntegTest.exec"
    }
  }
}

sonarRunner {
    sonarProperties {
        property "sonar.projectName", "test-samples"
        property "sonar.projectKey", "jsebfranck.samples"
    }
}

Explanations

I used Jacoco to generate my tests coverage indicators :

  apply plugin: 'jacoco'


The following lines allow to configure my integration tests. To distinguish these tests from the unit tests, I moved them in a specific source folder : "src/integtest/java". Please note that with gradle, the default test folder is "src/test/java" and I use it for my unit tests.

  sourceSets {
    integtest {
      java {
        compileClasspath += main.output
        runtimeClasspath += main.output
        srcDir 'src/integtest/java'
      }
    }
  }

  configurations {
    integtestCompile.extendsFrom testCompile
  }

  task "integtest"(type: Test, dependsOn: integtestClasses) {
    testClassesDir = sourceSets.integtest.output.classesDir
    classpath = sourceSets.integtest.runtimeClasspath
  }

I configured Jacoco to generate the tests coverage data in a specific directory : one for the unit tests and for the integration tests :

  task "integtest"(type: Test, dependsOn: integtestClasses) {
    testClassesDir = sourceSets.integtest.output.classesDir
    classpath = sourceSets.integtest.runtimeClasspath

      jacoco {
          destinationFile = file("$buildDir/jacoco/jacocoIntegTest.exec")
      }
  }

  test {
    jacoco {
      destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
    }
  }

Then for each module, I configured sonar to use generated Jacoco data :
  • reportPath property allows to configure the unit tests coverage
  • itReportPath property allows to configure the integration tests coverage
allprojects {
  sonarRunner {
    sonarProperties {
      property "sonar.jacoco.reportPath", "$buildDir/jacoco/jacocoTest.exec"
      property "sonar.jacoco.itReportPath", "$buildDir/jacoco/jacocoIntegTest.exec"
    }
  }
}

Finally I configured my sonar instance. Here I use the default parameters so the report is generated on my localhost sonar installation and its h2 database :

sonarRunner {
    sonarProperties {
        property "sonar.projectName", "test-samples"
        property "sonar.projectKey", "jsebfranck.samples"
    }
}


Source code

Please find the complete source code on my github repository about tests.



dimanche 5 janvier 2014

Mockito in the trenches

I used EasyMock framework for three years, before starting to use Mockito two years ago and I'm now really happy with this framework.

However, it provides some features I never used, and for some features it provides several ways to write your tests. For example you have two ways to create your mocks and two ways to write your expectations.

So, in this article I will present every feature I use, and how I choose to write my Mockito tests.

Our example

Let's start with a simple example, then we will go deeper into the framework.

The class we want to test is a class managing accounts, AccountService, with a single dependency, its repository : AccountRepository. For the moment, AccountService has only one method :

public class AccountService {
  @Inject
  private AccountRepository accountRepository;

  public Account getAccountByLogin(String login) {
    try {
      return accountRepository.findAccount(login);
    } catch (EntityNotFoundException enfe) {
      return null;
    }
  }
}

How can we test that with Mockito?

Mocks creation


The first thing you have to do is to create your class of test and create your mocks. I recommend to use the Mockito annotations and the Junit runner as it is more elegant and concise :

@RunWith(MockitoJUnitRunner.class)
public class AccountServiceTest {
  @InjectMocks
  private AccountService accountService;

  @Mock
  private AccountRepository accountRepository;
}

As you can see, you don't need a @Before method and you don't have to instantiate your objects. All is done automatically by the framework. To inject the mocks in the class to test, Mockito tries to do that using firstly the object constructor, then the object setters or finally the object properties.

doReturn and verify


Now let's test the method getAccountByLogin and the case where an account already exists.

  private static final String LOGIN = "login";
  private static final String PASSWORD = "password";

  @Test
  public void getAccountByLogin_withExistingAccount_shouldReturnTheAccount() 
    throws Exception {
    // Given
    Account existingAccount = new Account(LOGIN, PASSWORD);
    doReturn(existingAccount).when(accountRepository).findAccount(LOGIN);

    // When
    Account result = accountService.getAccountByLogin(LOGIN);

    // Then
    assertEquals(existingAccount, result);
    verify(accountRepository).findAccount(LOGIN);
    verifyNoMoreInteractions(accountRepository);
  }

Explanations :

  • doReturn allows to override the behavior of the AccountRepository.findAccount method. Here we return an Account object to simulate the case that an account already exists
  • verify(accountRepository).findAccount allows to check that this method has been called
  • verifyNoMoreInteractions method allows to be sure that we didn't call another method on this mock. It is useful in that case because you test that you don't do a useless call on your repository

doThrow

Now let's test the case where the account doesn't exist. In that case the repository throws an EntityNotFoundException :

  @Test
  public void getAccountByLogin_withUnexistingAccount_shouldReturnNull() throws Exception {
    // Given
    doThrow(new EntityNotFoundException()).when(accountRepository).findAccount(LOGIN);

    // When
    Account result = accountService.getAccountByLogin(LOGIN);

    // Then
    assertNull(result);
  }

As we used doReturn before, here we use doThrow method. Easy!

doReturn vs thenReturn, doThrow vs thenThrow

With mockito the following instructions are similar :

  // either :
  doReturn(null).when(accountService).getAccountByLogin(LOGIN);
  // or :  
  when(accountService.getAccountByLogin(LOGIN)).thenReturn(null);

  // either :
  doThrow(new EntityNotFoundException()).when(accountRepository).findAccount(LOGIN);
  // or :
  when(accountRepository.findAccount(LOGIN)).thenThrow(new EntityNotFoundException());

However, in the case you want to test a void method, you can write :

  doThrow(new EntityNotFoundException()).when(accountRepository).deleteAccount(LOGIN);

But you cannot write the following instruction because it doesn't compile :

  when(accountRepository.deleteAccount(LOGIN)).thenThrow(new EntityNotFoundException());

So I recommend to always use the do* methods in order to keep your tests coherent.

Object.equals and argument captor


Now let's add another method which create an account :

  public void createAccount(String login, String password) throws ServiceException {
    Account account = new Account(login, password);
    accountRepository.createAccount(account);
  }

It seems very easy to write this test. Let's do a first try :

  @Test
  public void createAccount_nominalCase_shouldCreateTheAccount() throws Exception {
    // When
    accountService.createAccount(LOGIN, PASSWORD);

    // Then
    verify(accountRepository).createAccount(new Account(LOGIN, PASSWORD));   
    verifyNoMoreInteractions(accountRepository);
  }

But unfortunately the test fails! Why? Because the verify instruction checks that the parameters passed in the createAccount method are the same in the test that in the tested code. However, in that case, the Account object has no equals method.

You may think to add an equals method in the Account object but if you do that only for your unit test, it is really a shame. Hopefully Mockito provides a cleaner way to test this case : the argument captor.

  @Test
  public void createAccount_nominalCase_shouldCreateTheAccount() throws Exception {
    // When
    accountService.createAccount(LOGIN, PASSWORD);

    // Then
    assertThatAccountAsBeenCreated();
    verifyNoMoreInteractions(accountRepository);
  }
  
  private void assertThatAccountAsBeenCreated() {
    ArgumentCaptor argument = ArgumentCaptor.forClass(Account.class);
    verify(accountRepository).createAccount(argument.capture());
    Account createdAccount = argument.getValue();

    assertEquals(LOGIN, createdAccount.getLogin());
    assertEquals(PASSWORD, createdAccount.getPassword());    
  }

With this technic, you can retrieve the object passed in the tested code, then do every assertion you want. Here we just want to be sure that the login and the password are correct.

Partial mocking

Now let's add three lines of code in our createAccount method to check that the account doesn't exist before we create it. To do that, we use the existing method getAccountByLogin :

  public void createAccount(String login, String password) throws ServiceException {
    if (getAccountByLogin(login) != null) {
     throw new ServiceException(String.format("The account %s already exists", login));
    }

    Account account = new Account(login, password);
    accountRepository.createAccount(account);
  }

As you have already tested the getAccountByLogin, you don't want to test it again because our tests could become unmaintainable.

So here you can use the partial mocking. The idea is to mock the call to the getAccountByLogin method within the class you are testing. With Mockito (unlike other mock frameworks) it is very easy to do that. You just have to override your method behavior like if you were using a mock :

  @Test
  public void createAccount_nominalCase_shouldCreateTheAccount() throws Exception {
    // Given
    doReturn(null).when(accountService).getAccountByLogin(LOGIN);

    // When
    accountService.createAccount(LOGIN, PASSWORD);

    // Then
    assertThatAccountAsBeenCreated();
    verifyNoMoreInteractions(accountRepository);
    verify(accountService).getAccountByLogin(LOGIN);
  }

Then you just have to add the @Spy annotation on the declaration of your tested object :

  @InjectMocks
  @Spy
  private AccountService accountService;

And it works!

Conclusion

I think I covered every feature of Mockito I use every day. Don't hesitate to ping me if I forgot something important. Anyway, I hope this tutorial helped you to have a better understanding of this great framework!

The whole code, with more cases and tests, is available on my github account.

Also, don't hesitate to consult my recommendations to write maintainable unit tests.

Cheers!