Understanding outside-in

Exclusive offer: get 50% off this eBook here
Test-Driven Development with Mockito

Test-Driven Development with Mockito — Save 50%

Learn how to apply Test-Driven Development and the Mockito framework in real life projects, using realistic, hands-on examples with this book and ebook.

$23.99    $12.00
by Sujoy Acharya | November 2013 | Open Source

In this article by Sujoy Acharya, author of the book Test-Driven Development with Mockito, we will cover different styles of TDD and write code using them. Generally, the outside-in approach covers use case level functionality or is intended for acceptance tests. These tests provide regression suits and system documentation; if they fail, user/customer acceptance also fails.

(For more resources related to this topic, see here.)

In this category, developers pick a story or use case and drill into low-level unit tests. Basically, the objective is to obtain high-level design. The different system interfaces are identified and abstracted. Once different layers/interfaces are identified, unit-level coding can be started.

Here, developers look at the system boundary and create a boundary interface depending upon a use case/story. Then, collaborating classes are created. Mock objects can act as a collaborating class. This approach of development relies on code for abstraction.

Acceptance Test-Driven Development (ATDD) falls into this category. FitNesse fixtures provide support for ATDD. This is stateful. It is also known as the top-down approach.

An example of ATDD

As a health professional (doctor), I should get the health information of all my critical patients who are admitted as soon as I'm around 100 feet from the hospital.

Here, how patient information is periodically stored in the server, how GPS tracks the doctor, how the system registers the doctor's communication medium (sends report to the doctor by e-mail or text), and so on can be mocked out. A test will be conducted to deal with how to fetch patient data for a doctor and send the report quickly. Gradually, other components will be coded.

The preceding figure represents the high-level components of the user story.

Here, Report Dispatcher is notified when a doctor approaches a hospital, then the dispatcher fetches patient information for the doctor and sends him the patient record. Patient Information, Outbound Messaging Interface, and Location Sensor (GPS) parts are mocked, and the dispatcher acts as a collaborator.

Now we have a requirement to calculate the taxable income from the total income, calculate the payable tax, and send an e-mail to the client with details.

We have to gather the annual income, medical expense, house loan premium, life insurance details, provident fund deposit, and apply the following rule to calculate the taxable income:

  • Up to USD 100,000 is not taxable and can be invested as medical insurance, provident fund, or house loan principal payment
  • Up to USD 150,000 can be used as house rent or house loan interest

Now we will build a TaxConsultant application using the outside-in style.

Following are the steps:

  1. Create a new test class com.packtpub.chapter04.outside. in.TaxConsultantTest under the test source folder.
  2. We need to perform three tasks; that are, calculate the taxable income, the payable tax, and send an e-mail to a client. We will create a class TaxConsultant to perform these tasks. We will be using Mockito to mock out external behavior. Add a test to check that when a client has investment, then our consultant deducts an amount from the total income and calculates the taxable income. Add a test when_deductable_present_then_taxable_income_is_less_than_the_total_income() to verify it so that it can calculate the taxable income:

    @Test
    public void when_deductable_present_then_taxable_income_
    is_less_than_the_total_income () {
    TaxConsultant consultant = new TaxConsultant();
    }

    Add the class under the src source folder. Now we have to pass different amounts to the consultant. Create a method consult() and pass the following values:

    @Test
    public void when_deductable_present_then_taxable_income_is_less_
    than_the_total_income () {
    TaxConsultant consultant = new TaxConsultant();
    double totalIncome = 1200000;
    double homeLoanInterest = 150000;
    double homeLoanPrincipal =20000;
    double providentFundSavings = 50000;
    double lifeInsurancePremium = 30000;
    consultant.consult(totalIncome,homeLoanInterest,
    homeLoanPrincipal,providentFundSavings,
    lifeInsurancePremium);
    }

    In the outside-in approach, we mock out objects with interesting behavior. We will mock out taxable income behavior and create an interface named TaxbleIncomeCalculator. This interface will have a method to calculate the taxable income. We read that a long parameter list is code smell; we will refactor it later:

    public interface TaxbleIncomeCalculator {
    double calculate(double totalIncome, double homeLoanInterest,
    double homeLoanPrincipal, double providentFundSavings, double
    lifeInsurancePremium);
    }

  3. Pass this interface to TaxConsultant as the constructor argument:

    @Test
    public void when_deductable_present_then_taxable_income_is_less_
    than_the_total_income () {
    TaxbleIncomeCalculator taxableIncomeCalculator = null;
    TaxConsultant consultant = new TaxConsultant
    (taxableIncomeCalculator);

    We need a tax calculator to verify that behavior. Create an interface called TaxCalculator:

    public interface TaxCalculator {
    double calculate(double taxableIncome);
    }

  4. Pass this interface to TaxConsultant:

    TaxConsultant consultant = new TaxConsultant(taxableIncomeCalculat
    or,taxCalculator);

    Now, time to verify the collaboration. We will use Mockito to create mock objects from the interfaces. For now, the @Mock annotation creates a proxy mock object. In the setUp method, we will use MockitoAnnotations.initMocks(this); to create the objects:

    @Mock TaxbleIncomeCalculator taxableIncomeCalculator;
    @Mock TaxCalculator taxCalculator;
    TaxConsultant consultant;
    @Before
    public void setUp() {
    MockitoAnnotations.initMocks(this);
    consultant= new TaxConsultant(
    taxableIncomeCalculator,taxCalculator);
    }

  5. Now in test, verify that the consultant class calls TaxableIncomeCalculator and TaxableIncomeCalculator makes a call to
  6. TaxCalculator. Mockito has the verify method to test that:

    verify(taxableIncomeCalculator, only())
    calculate(eq(totalIncome), eq(homeLoanInterest),
    eq(homeLoanPrincipal), eq(providentFundSavings),
    eq(lifeInsurancePremium));
    verify(taxCalculator,only()).calculate(anyDouble());

    Here, we are verifying that the consultant class delegates the call to mock objects. only() checks that the method was called at least once on the mock object. eq() checks that the value passed to the mock object's method is equal to some value.

    Here, the test will fail since we don't have the calls. We will add the following code to pass the test:

    public class TaxConsultant {
    private final TaxbleIncomeCalculator taxbleIncomeCalculator;
    private final TaxCalculator calculator;
    public TaxConsultant(TaxbleIncomeCalculator
    taxableIncomeCalculator, TaxCalculator calc) {
    this.taxbleIncomeCalculator =
    taxableIncomeCalculator;
    this.calculator = calc;
    }
    public void consult(double totalIncome, double homeLoanInterest,
    double homeLoanPrincipal, double providentFundSavings, double
    lifeInsurancePremium) {
    double taxableIncome = taxbleIncomeCalculator.calculate
    (totalIncome,homeLoanInterest, homeLoanPrincipal,
    providentFundSavings,lifeInsurancePremium);
    double payableTax= calculator.calculate(taxableIncome);
    }
    }

    The test is being passed; we can now add another delegator for e-mail and call it EmailSender.

  7. Our facade class is ready. Now we need to use TDD for each interface we extracted. Similarly, we can apply TDD for TaxableIncomeCalculator and EmailSender.

Summary

This article provided an overview of classical and mockist TDD. In classical TDD, real objects are used and integrated, and mocks are only preferred if a real object is not easy to instantiate. In mockist TDD, mocks have higher priority than real objects.

Resources for Article:


Further resources on this subject:


Test-Driven Development with Mockito Learn how to apply Test-Driven Development and the Mockito framework in real life projects, using realistic, hands-on examples with this book and ebook.
Published: November 2013
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

About the Author :


Sujoy Acharya

Sujoy Acharya works as a software architect with Siemens Technology and Services Pvt. Ltd. (STS). He grew up in a joint family and pursued his graduation in the field of computer science and engineering. His hobbies are watching movies, playing outdoor sports, and downloading the latest movies.

He likes to research upcoming technologies. His major contributions are in the fields of Java, J2EE, Web service, Ajax, GWT, and Spring. He designs and develops healthcare software products.

He has over 10 years of industrial experience and has designed and implemented large-scale enterprise solutions.

Books From Packt


Metasploit Penetration Testing Cookbook, Second Edition
Metasploit Penetration Testing Cookbook, Second Edition

Software Testing using Visual Studio 2012
Software Testing using Visual Studio 2012

 Learning Software Testing with Test Studio
Learning Software Testing with Test Studio

Arquillian Testing Guide
Arquillian Testing Guide

Jasmine JavaScript Testing
Jasmine JavaScript Testing

Instant Mockito [Instant]
Instant Mockito [Instant]

Instant RSpec Test-Driven Development How-to [Instant]
Instant RSpec Test-Driven Development How-to [Instant]

Robot Framework Test Automation
Robot Framework Test Automation


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
N
F
M
H
i
9
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software