Thursday, March 24, 2016

Mocking in Test Driven Development



Some definitions:


Mocking the Embedded World:
Test-Driven Development, Continuous Integration, and Design Patterns
Michael Karlesky, Greg Williams, William Bereza, Matt Fletcher
Atomic Object, http://atomicobject.com
http://www.methodsandtools.com/archive/archive.php?id=59

A Note on "Mocking" and This Article’s Title
Mocking in software development is a specific practice that complements unit testing (in particular, interaction-based testing). The majority of a system’s code consists of calls making calls to other parts of the codebase. A mock is a specialized substitution for any part of the system with which the code under test interacts.

The mock not only mimics the function call interface of the system code outside the code under test it also provides the means to capture the parameters of function calls made upon it, record the order of calls made, and provide any function return value a programmer requires for testing scenarios. With mocks we can thoroughly test all of the logic within a function and verify that this code makes calls to the rest of the system as expected. Mocking is covered in more depth later.

Automated unit testing is far more prevalent in high-level software systems than in embedded systems though certainly even here it is not widespread. To our knowledge, automatically generating and unit testing with mocks in embedded software (particularly in small systems and those using C) such as we have done is a new development in the embedded space. This article’s title is a play on the uniqueness of the mocking concept to embedded software and a reaction to those in the industry that may say practices such as TDD are impossible to implement or have no value in embedded software development.

Wikipedia Test-driven development 

Fakes, mocks and integration tests
Unit tests are so named because they each test one unit of code. A complex module may have a thousand unit tests and a simple module may have only ten. The tests used for TDD should never cross process boundaries in a program, let alone network connections. Doing so introduces delays that make tests run slowly and discourage developers from running the whole suite. Introducing dependencies on external modules or data also turns unit tests into integration tests. If one module misbehaves in a chain of interrelated modules, it is not so immediately clear where to look for the cause of the failure.
When code under development relies on a database, a web service, or any other external process or service, enforcing a unit-testable separation is also an opportunity and a driving force to design more modular, more testable and more reusable code.[33] Two steps are necessary:
  1. Whenever external access is needed in the final design, an interface should be defined that describes the access available. See the dependency inversion principle for a discussion of the benefits of doing this regardless of TDD.
  2. The interface should be implemented in two ways, one of which really accesses the external process, and the other of which is a fake or mock. Fake objects need do little more than add a message such as “Person object saved” to a trace log, against which a test assertion can be run to verify correct behaviour. Mock objects differ in that they themselves contain test assertions that can make the test fail, for example, if the person's name and other data are not as expected.
Fake and mock object methods that return data, ostensibly from a data store or user, can help the test process by always returning the same, realistic data that tests can rely upon. They can also be set into predefined fault modes so that error-handling routines can be developed and reliably tested. In a fault mode, a method may return an invalid, incomplete or null response, or may throw anexception. Fake services other than data stores may also be useful in TDD: A fake encryption service may not, in fact, encrypt the data passed; a fake random number service may always return 1. Fake or mock implementations are examples of dependency injection.
A Test Double is a test-specific capability that substitutes for a system capability, typically a class or function, that the UUT depends on. There are two times at which test doubles can be introduced into a system: link and execution. Link time substitution is when the test double is compiled into the load module, which is executed to validate testing. This approach is typically used when running in an environment other than the target environment that requires doubles for the hardware level code for compilation. The alternative to linker substitution is run-time substitution in which the real functionality is replaced during the execution of a test cases. This substitution is typically done through the reassignment of known function pointers or object replacement.
Test doubles are of a number of different types and varying complexities:
  • Dummy – A dummy is the simplest form of a test double. It facilitates linker time substitution by providing a default return value where required.
  • Stub – A stub adds simplistic logic to a dummy, providing different outputs.
  • Spy – A spy captures and makes available parameter and state information, publishing accessors to test code for private information allowing for more advanced state validation.
  • Mock – A mock is specified by an individual test case to validate test-specific behavior, checking parameter values and call sequencing.
  • Simulator – A simulator is a comprehensive component providing a higher-fidelity approximation of the target capability (the thing being doubled). A simulator typically requires significant additional development effort.[8]
A corollary of such dependency injection is that the actual database or other external-access code is never tested by the TDD process itself. To avoid errors that may arise from this, other tests are needed that instantiate the test-driven code with the "real" implementations of the interfaces discussed above. These are integration tests and are quite separate from the TDD unit tests. There are fewer of them, and they must be run less often than the unit tests. They can nonetheless be implemented using the same testing framework, such as xUnit.
Integration tests that alter any persistent store or database should always be designed carefully with consideration of the initial and final state of the files or database, even if any test fails. This is often achieved using some combination of the following techniques:
  • The TearDown method, which is integral to many test frameworks.
  • try...catch...finally exception handling structures where available.
  • Database transactions where a transaction atomically includes perhaps a write, a read and a matching delete operation.
  • Taking a "snapshot" of the database before running any tests and rolling back to the snapshot after each test run. This may be automated using a framework such as Ant or NAnt or a continuous integration system such as CruiseControl.
  • Initialising the database to a clean state before tests, rather than cleaning up after them. This may be relevant where cleaning up may make it difficult to diagnose test failures by deleting the final state of the database before detailed diagnosis can be performed.


Mockito - Official Site
site.mockito.org
A landing page for information about Mockito framework, a mocking framework for unit tests written in Java.

Mockito - Wikipedia, the free encyclopedia
Mockito is an open source testing framework for Java released under the MIT License. [1] [2] The framework allows the creation of test double objects (mock objects ...
Mockito is an open source testing framework for Java released under the MIT License.[1][2] The framework allows the creation of test double objects (mock objects) in automated unit tests for the purpose of Test-driven Development (TDD) or Behavior Driven Development (BDD).
In software development there is an opportunity of ensuring that objects perform the behaviors that are expected of them. One approach is to create a test automation framework that actually exercises each of those behaviors and verifies that it performs as expected, even after it is changed. However, the requirement to create an entire testing framework is often an onerous task that requires as much effort as writing the original objects that were supposed to be tested. For that reason, developers have created mock testing frameworks. These effectively fake some external dependencies so that the object being tested has a consistent interaction with its outside dependencies. Mockito intends to streamline the delivery of these external dependencies that are not subjects of the test. A study performed in 2013 on 10,000 GitHub projects found that Mockito is the 9th most popular Java library. [3]

Distinguishing features[edit]

Mockito distinguishes itself from other mocking frameworks by allowing developers to verify the behavior of the system under test (SUT) without establishing expectations beforehand.[4] One of the criticisms of mock objects is that there is a tight coupling of the test code to the system under test.[5] Since Mockito attempts to eliminate the expect-run-verify pattern[6] by removing the specification of expectations, the coupling is reduced or minimized. The result of this distinguishing feature is simpler test code that should be easier to read and modify. Mockito also provides some annotations useful for reducing boilerplate code.[7]

Origins[edit]

Szczepan Faber started the Mockito project after finding existing mock object frameworks too complex and difficult to work with. Faber began by expanding on the syntax and functionality of Easy Mock, but eventually rewriting most of Mockito.[8] Faber's goal was to create a new framework that was easier to work with and the Guardian project in London in early 2008.[9]

Usage[edit]

Mockito has a growing user-base[10][11] as well as finding use in other open source projects.[12]

Example[edit]

Consider this decoupled Hello world program; we may unit test some of its parts, using mock objects for other parts.
package org.examples;

import java.io.IOException;

public class HelloApplication {

   public static interface Greeter {
      String getGreeting(String subject);
      String getIntroduction(String actor);
   }
   
   public static class HelloGreeter implements Greeter {
      private String hello;
      private String segmenter;
      
      public HelloGreeter(String hello, String segmenter) {
         this.hello = hello;
         this.segmenter = segmenter;
      }
      public String getGreeting(String subject) {
         return hello + " " + subject; 
      }
      public String getIntroduction(String actor) {
         return actor+segmenter;
      }
   }
   
   public static interface HelloActable {
      void sayHello(String actor, String subject) throws IOException;
   }
   
   public static class HelloAction implements HelloActable {
      private Greeter helloGreeter;
      private Appendable helloWriter;

      public HelloAction(Greeter helloGreeter, Appendable helloWriter) {
         super();
         this.helloGreeter = helloGreeter;
         this.helloWriter = helloWriter;
      }
      public void sayHello(String actor, String subject) throws IOException { 
         helloWriter.append(helloGreeter.getIntroduction(actor)).append(helloGreeter.getGreeting(subject));
      }
   }

   public static void main(String... args) throws IOException {
      new HelloAction(new HelloGreeter("hello", ": "), System.out).sayHello("application", "world");
   }

}
The result of HelloApplication launching will be the following:
application: hello world
Unit test for HelloActable component may look like this:
package org.examples;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;

import org.examples.HelloApplication.HelloActable;
import org.examples.HelloApplication.HelloAction;
import org.examples.HelloApplication.Greeter;

public class HelloActionUnitTest {
   
   Greeter helloGreeterMock;
   Appendable helloWriterMock;
   HelloActable helloAction;
   
   @Before
   public void setUp() {
      helloGreeterMock = mock(Greeter.class);
      helloWriterMock = mock(Appendable.class);
      helloAction = new HelloAction(helloGreeterMock, helloWriterMock);
   }
   
   @Test
   public void testSayHello() throws Exception {
      when(helloWriterMock.append(any(String.class))).thenReturn(helloWriterMock);
      when(helloGreeterMock.getIntroduction(eq("unitTest"))).thenReturn("unitTest : ");
      when(helloGreeterMock.getGreeting(eq("world"))).thenReturn("hi world");
      
      helloAction.sayHello("unitTest", "world");
      
      verify(helloGreeterMock).getIntroduction(eq("unitTest"));
      verify(helloGreeterMock).getGreeting(eq("world"));

      verify(helloWriterMock, times(2)).append(any(String.class));
      verify(helloWriterMock, times(1)).append(eq("unitTest : "));
      verify(helloWriterMock, times(1)).append(eq("hi world"));
   }
}
It uses mock objects for the Greeter and Appendable interfaces, and implicitly assumes the next use case:
unitTest : hi world
Integration test code for testing HelloActable wired together with Greeter may look like the following:
package org.examples;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;

import org.examples.HelloApplication.HelloActable;
import org.examples.HelloApplication.HelloAction;
import org.examples.HelloApplication.Greeter;
import org.examples.HelloApplication.HelloGreeter;

public class HelloActionIntegrationTest {
   HelloActable helloAction;
   Greeter helloGreeter;
   Appendable helloWriterMock;
   
   @Before
   public void setUp() {
      helloGreeter = new HelloGreeter("welcome", " says ");
      helloWriterMock = mock(Appendable.class);
      helloAction = new HelloAction(helloGreeter, helloWriterMock);
   }
   
   @Test
   public void testSayHello() throws Exception {
      when(helloWriterMock.append(any(String.class))).thenReturn(helloWriterMock);

      helloAction.sayHello("integrationTest", "universe");  

      verify(helloWriterMock, times(2)).append(any(String.class));
      verify(helloWriterMock, times(1)).append(eq("integrationTest says "));
      verify(helloWriterMock, times(1)).append(eq("welcome universe"));
   }
}
It uses mock objects only in place of Appendable interfaces, and uses the real implementations for other (HelloActable and Greeter) interfaces, and implicitly assumes the next use case:
integrationTest says welcome universe
As can be seen from the import statements of HelloActionUnitTest and HelloActionIntegrationTest classes, it is necessary to put some Mockito jars and JUnit jars in your class path to be able to compile and run the test classes.

See also[edit]


References[edit]

  1. Jump up^ "Mockito in six easy examples". 2009. Retrieved 2012-10-05.
  2. Jump up^ "What's the best mock framework for Java?". Retrieved 2010-12-29.
  3. Jump up^ Weiss, Tal (2013-11-26). "GitHub’s 10,000 most Popular Java Projects – Here are The Top Libraries They Use". Retrieved 2014-03-11.
  4. Jump up^ "Features and Motivations". Retrieved 2010-12-29.
  5. Jump up^ Fowler, Martin (2007). "Mocks Aren't Stubs". Retrieved 2010-12-29.
  6. Jump up^ Faber, Szczepan. "Death Wish". Retrieved 2010-12-29.
  7. Jump up^ Kaczanowski,, Tomek. "Mockito - Open Source Java Mocking Framework". Retrieved 2013-09-17.
  8. Jump up^ Faber, Szczepan. "Mockito". Retrieved 2010-12-29.
  9. Jump up^ "Mockito Home Page". Retrieved 2010-12-29.
  10. Jump up^ http://www.google.com/trends/explore#q=mockito,easymock,jmock
  11. Jump up^ "Mockito User Base". Retrieved 2010-12-29.
  12. Jump up^ "Mockito in Use". Retrieved 2010-12-29.
External links[edit]
Official website
mockito on GitHub
Mockito javadoc
Mockito in six easy examples
Java Mocking Frameworks

Mockito in six easy examples - Gojko Adzic
gojko.net/2009/10/23/mockito-in-six-easy-examples
Mockito is a fantastic mock library for Java. I’m fascinated by how easy it is to use, compared to other things out there both in the Java and .NET world.

Unit tests with Mockito - Tutorial - vogella
www.vogella.com/tutorials/Mockito/article.html
Testing with Mockito This tutorial explains testing with the Mockito framework from within the Eclipse IDE.

No comments:

Post a Comment