Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mockito Essentials

You're reading from   Mockito Essentials A practical guide to get you up and running with unit testing using Mockito

Arrow left icon
Product type Paperback
Published in Oct 2014
Publisher
ISBN-13 9781783983605
Length 214 pages
Edition 1st Edition
Tools
Arrow right icon
Author (1):
Arrow left icon
Sujoy Acharya Sujoy Acharya
Author Profile Icon Sujoy Acharya
Sujoy Acharya
Arrow right icon
View More author details
Toc

Working with stubs

A stub delivers indirect inputs to the caller when the stub's methods are called. Stubs are programmed only for the test scope. Stubs may record other information such as how many times they are invoked and so on.

Unit testing a happy path is relatively easier than testing an alternate path. For instance, suppose that you need to simulate a hardware failure or transaction timeout scenario in your unit test, or you need to replicate a concurrent money withdrawal for a joint account use case—these scenarios are not easy to imitate. Stubs help us to simulate these conditions. Stubs can also be programmed to return a hardcoded result; for example, a stubbed bank account object can return the account balance as $100.00.

The following steps demonstrate stubbing:

  1. Launch Eclipse, open <work_space>, and go to the 3605OS_TestDoubles project.
  2. Create a com.packt.testdoubles.stub package and add a CreateStudentResponse class. This Plain Old Java Object (POJO) contains a Student object and an error message:
      public class CreateStudentResponse {
        private final String errorMessage;
        private final Student student;
    
        public CreateStudentResponse(String errorMessage, Student student) {
          this.errorMessage = errorMessage;
          this.student = student;
        }
        public boolean isSuccess(){
          return null == errorMessage;
        }
    
        public String getErrorMessage() {
          return errorMessage;
        }
         public Student getStudent() {
         return student;
        }
      }
  3. Create a StudentDAO interface and add a create() method to persist a student's information. The create () method returns the roll number of the new student or throws an SQLException error. The following is the interface definition:
    public interface StudentDAO {
      public String create(String name, String className)
      throws SQLException;
    }
  4. Create an interface and implementation for the student's registration. The following service interface accepts a student's name and a class identifier and registers the student to a class. The create API returns a CreateStudentResponse. The response contains a Student object or an error message:
    public interface StudentService {
      CreateStudentResponse create(String name, String studentOfclass);
    }

    The following is the service implementation:

    public class StudentServiceImpl implements StudentService {
      private final StudentDAO studentDAO;
    
      public StudentServiceImpl(StudentDAO studentDAO) {
        this.studentDAO = studentDAO;
      }
    
      @Override public CreateStudentResponse create(String name, String studentOfclass) {
        CreateStudentResponse response = null;
        try{
          String roleNum= studentDAO.create (name, studentOfclass);
          response = new CreateStudentResponse(null, new Student(roleNum, name));
        }catch(SQLException e) {){
          response = new CreateStudentResponse
          ("SQLException"+e.getMessage(),  null);
        }catch (Exception e) {
          response = new CreateStudentResponse(e.getMessage(), null);
        }
        return response;
      }
    }

    Note

    Note that the service implementation class delegates the Student object's creation task to the StudentDAO object. If anything goes wrong in the data access layer, then the DAO throws an SQLException error. The implementation class catches the exceptions and sets the error message to the response object.

  5. How can you test the SQLException condition? Create a stub object and throw an exception. Whenever the create method is invoked on the stubbed DAO, the DAO throws an exception. The following ConnectionTimedOutStudentDAOStub class implements the StudentDAO interface and throws an SQLException error from the create() method:
    package com.packt.testdoubles.stub;
    import java.sql.SQLException;
    
    public class ConnectionTimedOutStudentDAOStub implements StudentDAO {
      public String create(String name, String className)
      throws SQLException {
        throw new SQLException("DB connection timed out");
      }
    }

    This class should be created under the test source folder since the class is only used in tests.

  6. Test the SQLException condition. Create a test class and pass the stubbed DAO to the service implementation. The following is the test code snippet:
    public class StudentServiceTest {
      private StudentService studentService;
      @Test
      public void when_connection_times_out_then_the_student_is_not_saved() {
        studentService = new StudentServiceImpl(new ConnectionTimedOutStudentDAOStub());
        String classNine = "IX";
        String johnSmith = "john Smith";
        CreateStudentResponse resp = studentService.create(johnSmith, classNine);
        assertFalse(resp.isSuccss());
      }
    }

    The error condition is stubbed and passed into the service implementation object. When the service implementation invokes the create() method on the stubbed DAO, it throws an SQLException error.

Stubs are very handy to impersonate error conditions and external dependencies (you can achieve the same thing with a mock; this is just one approach). Suppose you need to test a code that looks up a JNDI resource and asks the resource to return some value. You cannot look up a JNDI resource from a JUnit test; you can stub the JNDI lookup code and return a stubbed object that will give you a hardcoded value.

You have been reading a chapter from
Mockito Essentials
Published in: Oct 2014
Publisher:
ISBN-13: 9781783983605
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image