Advanced Unit Testing for Java By Denilson Nastacio Mastering  Mock Objects
Your Host Denilson Nastacio 14 years in software development Quality Enthusiast Rational Unified Process practitioner RTP Scrolls ( http://rtpscrolls.blogspot.com ) SourcePatch ( http://sourcepatch.blogspot.com ) LinkedIn ( http://www.linkedin.com/in/nastacio )
Agenda Concepts Intercepting methods Declaring expectations Tools Q&A
Different levels of abstraction Code logic Tests whether isolated methods respect their exposed contract Guarantees that there are no broken code paths No runtime dependencies: mock objects Integration test (by developer, not QA organization) Tests combination of classes and runtime environment Require runtime support Detect incompatibilities between components Residual code logic tests Function test (by developer, not QA organization) Real end-user scenarios Residual code logic and integration test. A C E D B A C E B A C E D B
Ideal resource allocation Code logic Integration Function QA Function Test Development Dev QA System Test Runtime dependencies Cost per volume of code
The case against system dependencies on unit testing Complex Create user accounts, upgrade OS, install fixpacks, etc Slow Minutes to recycle servers between tests Unnecessary During development, you want to test the code, purge logic errors before starting test integration
Code logic test Classes tested in isolation Black box testing Based on declared interfaces, not actual implementation Guarantees that methods respect their declared interfaces Good to validate public APIs Bad for validating exceptions related to environment problems White box testing Based on implementation, usually due to incomplete specifications Typical of test written after the fact Concerned with exhaustive test of all lines in the actual source code Good to verify exception handling when combined with mock objects
Mock environments for Java
Classes of mock environments Environment simulators Respond like the real environment Pros: Simulate complex behavior without environment dependencies Cons: Few simulators available, maintaining a simulator rivals the complexity of maintaining a real application Mock object frameworks Same interfaces as the real environment Developer must preset the mock objects with the expected responses Pros: Mock objects can be generated quickly for any environment Cons: Presetting mock objects for unit tests may require lots of code
Mock libraries JMockit Instructs the JVM to replace calls to any method with code under your control One-two punch with JMock against bunkered initialization within the production code, such as calls to constructors or static methods Use JMockit to intercept calls to static methods deep into the production code and return JMock pre-programmed objects. http://jmockit.dev.java.net   JMock Pre-program objects to expect calls and return values of your choice Instruct the production code to “talk to” mocked object instead of actual system dependency Mocks interfaces and classes. http://www.jmock.org
Anatomy of JMock in a test fixture @Test public   void  testTransferFunds()  throws  Exception { org.jmock.Mockery context =  new  Mockery(); context.setImposteriser(ClassImposteriser. INSTANCE ); final   float  testAmount = 300; final  BankAccount sourceAccount = context.mock(BankAccount. class ,  "source" ); final  BankAccount targetAccount = context.mock(BankAccount. class ,  "target" ); org.jmock.Expectations expect =  new  Expectations() { {   one(sourceAccount).withdraw(testAmount); one(targetAccount).deposit(testAmount); } }; context.checking(expect); Transaction tx =  new  Transaction(); tx.transferFunds(testAmount, sourceAccount, targetAccount);   context.assertIsSatisfied(); } Create mock Context Create mock instances Programs mock instances Adds expectation to mock context. Asks context whether all expectations were met.
Anatomy of JMockit in a test fixture – Inlined mock @Mocked   private   final  BankSOAUtil  unused  =  null ; @Test public   void  testBankAccountSOA()  throws  Exception { String inputDir =  "abc" ; final  String inputFile =  "AndrewBankAccountData.xml" ; new  mockit.Expectations() { { BankSOAUtil. getInputStream ((URL)withNotNull()); returns( new  FileInputStream(inputFile)); } }; // Bank account constructor reads its configuration using // BankSOAUtil.getInputStream BankAccount bc =  new  BankAccount( "userid" ,  "password" ); Assert. assertEquals ( "Andrew" , bc.getCustomerName()); } Inlined mocked expectation Programming the expectation Marking class to be mocked
Anatomy of JMockit in a test fixture – Using a mock class public void testBankAccountSOA() throws Exception {s Mockit.setUpMocks(MockBankSOAUtil.class); String inputFile = "AndrewBankAccountData.xml"; // Bank account constructor reads its configuration using  // BankSOAUtil. getInputStream BankAccount bc = new BankAccount(...); Assert.assertEquals("Andrew", bc.getCustomerName()); Mockit.tearDownMocks(); } @MockClass(realClass = BankSOAUtil.class) public static class  MockBankSOAUtil  { private static String inputFile = null; @Mock(invocations = 1) public static InputStream  getInputStream (URL inputUrl) throws IOException { return new FileInputStream(inputFile) ; } public static void setInputFile(String inputFile) { MockDogearUtil.inputFile = inputFile ; } } Instructs the JVM about the mock classes to be used Instructs the JVM to stop using JMockit mocks. Declares the production class to be mocked Indicates which methods of the production class should be mocked
Which one should I use? JMockit Can intercept any call to the JVM Significant improvements on expectation support during 2009 Supports bytecode level coverage metrics My new favorite JMock Used to have better control over behavior of mocked object, my former favorite Needs production code to provide “entry points” to receive the mocked objects
Building mock expectations Required versus allowed Is it important that the mocked method is called? JMock: allowing/ignored/one JMockit: Expectations, Verifications, and sub-classes Specific versus loose Is it important that the mocked method is called with a specific parameter? Both JMock and JMockit offer out-of-the-box mathcers for concepts like 'same value', 'same class', 'inherited from a class', 'null', 'not null', and others
When results matter – 1 of 3 What if results from dependency matter? public   class  ExternalClass { public  String somethingWithAReturnValue(String input) { return   "DEF" ; }
When results matter – JMock  2 of 3 final  ExternalClass ecMock = context.mock(ExternalClass. class ); org.jmock.Expectations expect =  new  org.jmock.Expectations() { { one(ecMock).somethingWithAReturnValue( &quot;specific value&quot; ); will( returnValue ( &quot;someReturnValue&quot; )); } }; final  ExternalClass ecMock = context.mock(ExternalClass. class ); org.jmock.Expectations expect =  new  org.jmock.Expectations() { { one(ecMock).somethingWithAReturnValue(with( any (String. class ))); will( returnValue ( &quot;someReturnValue&quot; )); } }; Use with(any(Class <T> type)) to instruct the  JMock mock to ignore input parameters
When results matter – Jmockit -  3 of 3 new mockit.Expectations () {  ExternalClass EcMock; { ecMock.somethingWithAReturnValue( &quot;specific value&quot; ); returns( &quot;someReturnValue&quot; )); } }; new mockit.Expectations () {  ExternalClass EcMock; { ecMock.somethingWithAReturnValue(withAny( &quot;&quot; ); returns( &quot;someReturnValue&quot; )); } }; Use withAny(Class <T> type)) to instruct the  JMockit mock to ignore input parameters
Other great companion tools DDTUnit http://ddtunit.sourceforge.net/ Cobertura http://cobertura.sourceforge.net/   Note: JMockit has its own code coverage support

Mastering Mock Objects - Advanced Unit Testing for Java

  • 1.
    Advanced Unit Testingfor Java By Denilson Nastacio Mastering Mock Objects
  • 2.
    Your Host DenilsonNastacio 14 years in software development Quality Enthusiast Rational Unified Process practitioner RTP Scrolls ( http://rtpscrolls.blogspot.com ) SourcePatch ( http://sourcepatch.blogspot.com ) LinkedIn ( http://www.linkedin.com/in/nastacio )
  • 3.
    Agenda Concepts Interceptingmethods Declaring expectations Tools Q&A
  • 4.
    Different levels ofabstraction Code logic Tests whether isolated methods respect their exposed contract Guarantees that there are no broken code paths No runtime dependencies: mock objects Integration test (by developer, not QA organization) Tests combination of classes and runtime environment Require runtime support Detect incompatibilities between components Residual code logic tests Function test (by developer, not QA organization) Real end-user scenarios Residual code logic and integration test. A C E D B A C E B A C E D B
  • 5.
    Ideal resource allocationCode logic Integration Function QA Function Test Development Dev QA System Test Runtime dependencies Cost per volume of code
  • 6.
    The case againstsystem dependencies on unit testing Complex Create user accounts, upgrade OS, install fixpacks, etc Slow Minutes to recycle servers between tests Unnecessary During development, you want to test the code, purge logic errors before starting test integration
  • 7.
    Code logic testClasses tested in isolation Black box testing Based on declared interfaces, not actual implementation Guarantees that methods respect their declared interfaces Good to validate public APIs Bad for validating exceptions related to environment problems White box testing Based on implementation, usually due to incomplete specifications Typical of test written after the fact Concerned with exhaustive test of all lines in the actual source code Good to verify exception handling when combined with mock objects
  • 8.
  • 9.
    Classes of mockenvironments Environment simulators Respond like the real environment Pros: Simulate complex behavior without environment dependencies Cons: Few simulators available, maintaining a simulator rivals the complexity of maintaining a real application Mock object frameworks Same interfaces as the real environment Developer must preset the mock objects with the expected responses Pros: Mock objects can be generated quickly for any environment Cons: Presetting mock objects for unit tests may require lots of code
  • 10.
    Mock libraries JMockitInstructs the JVM to replace calls to any method with code under your control One-two punch with JMock against bunkered initialization within the production code, such as calls to constructors or static methods Use JMockit to intercept calls to static methods deep into the production code and return JMock pre-programmed objects. http://jmockit.dev.java.net JMock Pre-program objects to expect calls and return values of your choice Instruct the production code to “talk to” mocked object instead of actual system dependency Mocks interfaces and classes. http://www.jmock.org
  • 11.
    Anatomy of JMockin a test fixture @Test public void testTransferFunds() throws Exception { org.jmock.Mockery context = new Mockery(); context.setImposteriser(ClassImposteriser. INSTANCE ); final float testAmount = 300; final BankAccount sourceAccount = context.mock(BankAccount. class , &quot;source&quot; ); final BankAccount targetAccount = context.mock(BankAccount. class , &quot;target&quot; ); org.jmock.Expectations expect = new Expectations() { { one(sourceAccount).withdraw(testAmount); one(targetAccount).deposit(testAmount); } }; context.checking(expect); Transaction tx = new Transaction(); tx.transferFunds(testAmount, sourceAccount, targetAccount); context.assertIsSatisfied(); } Create mock Context Create mock instances Programs mock instances Adds expectation to mock context. Asks context whether all expectations were met.
  • 12.
    Anatomy of JMockitin a test fixture – Inlined mock @Mocked private final BankSOAUtil unused = null ; @Test public void testBankAccountSOA() throws Exception { String inputDir = &quot;abc&quot; ; final String inputFile = &quot;AndrewBankAccountData.xml&quot; ; new mockit.Expectations() { { BankSOAUtil. getInputStream ((URL)withNotNull()); returns( new FileInputStream(inputFile)); } }; // Bank account constructor reads its configuration using // BankSOAUtil.getInputStream BankAccount bc = new BankAccount( &quot;userid&quot; , &quot;password&quot; ); Assert. assertEquals ( &quot;Andrew&quot; , bc.getCustomerName()); } Inlined mocked expectation Programming the expectation Marking class to be mocked
  • 13.
    Anatomy of JMockitin a test fixture – Using a mock class public void testBankAccountSOA() throws Exception {s Mockit.setUpMocks(MockBankSOAUtil.class); String inputFile = &quot;AndrewBankAccountData.xml&quot;; // Bank account constructor reads its configuration using // BankSOAUtil. getInputStream BankAccount bc = new BankAccount(...); Assert.assertEquals(&quot;Andrew&quot;, bc.getCustomerName()); Mockit.tearDownMocks(); } @MockClass(realClass = BankSOAUtil.class) public static class MockBankSOAUtil { private static String inputFile = null; @Mock(invocations = 1) public static InputStream getInputStream (URL inputUrl) throws IOException { return new FileInputStream(inputFile) ; } public static void setInputFile(String inputFile) { MockDogearUtil.inputFile = inputFile ; } } Instructs the JVM about the mock classes to be used Instructs the JVM to stop using JMockit mocks. Declares the production class to be mocked Indicates which methods of the production class should be mocked
  • 14.
    Which one shouldI use? JMockit Can intercept any call to the JVM Significant improvements on expectation support during 2009 Supports bytecode level coverage metrics My new favorite JMock Used to have better control over behavior of mocked object, my former favorite Needs production code to provide “entry points” to receive the mocked objects
  • 15.
    Building mock expectationsRequired versus allowed Is it important that the mocked method is called? JMock: allowing/ignored/one JMockit: Expectations, Verifications, and sub-classes Specific versus loose Is it important that the mocked method is called with a specific parameter? Both JMock and JMockit offer out-of-the-box mathcers for concepts like 'same value', 'same class', 'inherited from a class', 'null', 'not null', and others
  • 16.
    When results matter– 1 of 3 What if results from dependency matter? public class ExternalClass { public String somethingWithAReturnValue(String input) { return &quot;DEF&quot; ; }
  • 17.
    When results matter– JMock 2 of 3 final ExternalClass ecMock = context.mock(ExternalClass. class ); org.jmock.Expectations expect = new org.jmock.Expectations() { { one(ecMock).somethingWithAReturnValue( &quot;specific value&quot; ); will( returnValue ( &quot;someReturnValue&quot; )); } }; final ExternalClass ecMock = context.mock(ExternalClass. class ); org.jmock.Expectations expect = new org.jmock.Expectations() { { one(ecMock).somethingWithAReturnValue(with( any (String. class ))); will( returnValue ( &quot;someReturnValue&quot; )); } }; Use with(any(Class <T> type)) to instruct the JMock mock to ignore input parameters
  • 18.
    When results matter– Jmockit - 3 of 3 new mockit.Expectations () { ExternalClass EcMock; { ecMock.somethingWithAReturnValue( &quot;specific value&quot; ); returns( &quot;someReturnValue&quot; )); } }; new mockit.Expectations () { ExternalClass EcMock; { ecMock.somethingWithAReturnValue(withAny( &quot;&quot; ); returns( &quot;someReturnValue&quot; )); } }; Use withAny(Class <T> type)) to instruct the JMockit mock to ignore input parameters
  • 19.
    Other great companiontools DDTUnit http://ddtunit.sourceforge.net/ Cobertura http://cobertura.sourceforge.net/ Note: JMockit has its own code coverage support