Transcript Document
Mocking Your Objects
with Impunity
7/7/2015
Presented by Ernest Hill
[email protected]
1
Goal of Presentation
7/7/2015
Show how “Mocking Objects” can
greatly improve unit testing by
facilitating tests that are easier to
write and less dependant upon
objects outside the test domain
Presented by Ernest Hill
[email protected]
2
Topics of Discussion
7/7/2015
What is Object Mocking?
Why Mock Objects?
What tools are available to support
Object Mockery
Presented by Ernest Hill
[email protected]
3
What is Object
Mocking?
7/7/2015
Creating a mock implementation
of an object that can be used as a
stand-in in testing
A mock objects allow you to set
expectations
The mock object lets you verify
that the expectations were met
Presented by Ernest Hill
[email protected]
4
Why engage in Object
Mocking?
7/7/2015
The real object has behaviour that
is hard to cause or is nondeterministic
The real object is difficult to set up
The real object is slow
The real object has (or is ) a UI
Test needs to query the object but
queries are not available
Real objects do not exist
Presented by Ernest Hill
[email protected]
5
What tools are available
to support Obect
Mockery
7/7/2015
The MockObjects framework
MockMaker
EasyMockt
Presented by Ernest Hill
[email protected]
6
MockObjects
Framework
7/7/2015
Open source framework available
at MockObjects.org
Provides some utility tools for
creating mock objects
Provides mock implementations of
common libraries such as IO,
Servlets and JDBC
Presented by Ernest Hill
[email protected]
7
MockMaker Overview
7/7/2015
Open source tool available at
mockmaker.org
Passive code generation tool
Generates mock objects that depend on
the MockObjects framework
Has a command line and gui interface
Mock objects can only be generated
from an interface
Presented by Ernest Hill
[email protected]
8
MockMaker Features
Generated MockObject has
Methods to set expected minimal
method call
Methods to set expected
parameter values
Methods to set return value from
method
Method to verify everything was as
expected
7/7/2015
Presented by Ernest Hill
[email protected]
9
MockMaker Drawbacks
7/7/2015
Interface being used is not directly
visible
If interface changes MockObject
must be modified or regenerated
No method to throw exceptions
Presented by Ernest Hill
[email protected]
10
EasyMock Overview
7/7/2015
Open source tool available at
easymock.org
Uses reflection to dynamically
create proxies that implement the
interface at run time
EasyMock generates two objects
the EasyMock Mock Object and
the EasyMock Mock Control
Presented by Ernest Hill
[email protected]
11
EasyMock Features
7/7/2015
Allows the expected parameter value to
be set for each method
Allows you to set up the value to be
returned by each method
Allows the number of times the method
is to be invoked to be specified
Allows you to specify an exception the a
method should throw
Will verify that everything went as
expected
Presented by Ernest Hill
[email protected]
12
EasyMock Drawbacks
7/7/2015
EasyMock generates objects on
the fly so you can’t add any
behaviour
EasyMock uses the equals method
to compare parameters
Presented by Ernest Hill
[email protected]
13
Test Domain
7/7/2015
We need to test a Copier class
The Copier constructor takes a
Reader and a Writer
The Copier copy method reads
from the Reader and Writes to the
Writer until the Reader returns null
Presented by Ernest Hill
[email protected]
14
Interfaces
public interface Reader {
public String readln();
}
public interface Writer {
public void writeln(String line);
}
7/7/2015
Presented by Ernest Hill
[email protected]
15
Copier
public class Copier {
private Reader reader;
private Writer writer;
public Copier(Reader aReader, Writer aWriter) {
this.reader = aReader;
this.writer = aWriter;
}
public void copy() {
String line;
while ( ( line = reader.readln() ) != null )
writer.writeln(line);
}
}
7/7/2015
Presented by Ernest Hill
[email protected]
16
Run MockMaker
java mockmaker.MockMaker Reader > MockReader.java
java mockmaker.MockMaker Writer > MockWriter.java
7/7/2015
Presented by Ernest Hill
[email protected]
17
MockReader.java
import mockmaker.ReturnValues;
import com.mockobjects.*;
import Reader;
public class MockReader implements Reader{
private ExpectationCounter myReadlnCalls = new ExpectationCounter("Reader ReadlnCalls");
private ReturnValues myActualReadlnReturnValues = new ReturnValues(false);
public void setExpectedReadlnCalls(int calls){
myReadlnCalls.setExpected(calls);
}
public String readln(){
myReadlnCalls.inc();
Object nextReturnValue = myActualReadlnReturnValues.getNext();
return (String) nextReturnValue;
}
public void setupReadln(String arg){
myActualReadlnReturnValues.add(arg);
}
public void verify(){
myReadlnCalls.verify();
}
Presented by Ernest Hill
}
7/7/2015
[email protected]
18
MockWriter.java
import mockmaker.ReturnValues;
import com.mockobjects.*;
import Writer;
public class MockWriter implements Writer{
private ExpectationCounter myWritelnCalls = new ExpectationCounter("Writer WritelnCalls");
private ExpectationList myWritelnParameter0Values = new ExpectationList("Writer
WritelnParameter0Values");
public void setExpectedWritelnCalls(int calls){
myWritelnCalls.setExpected(calls);
}
public void addExpectedWritelnValues(String arg0){
myWritelnParameter0Values.addExpected(arg0);
}
public void writeln(String arg0){
myWritelnCalls.inc();
myWritelnParameter0Values.addActual(arg0);
}
public void verify(){
myWritelnCalls.verify();
myWritelnParameter0Values.verify();
}
}
Presented by Ernest Hill
7/7/2015
[email protected]
19
Unit test using
MockMaker
public void testCopy() {
MockReader mockReader = new MockReader();
mockReader.setupReadln("ABC");
mockReader.setupReadln(null);
mockReader.setExpectedReadlnCalls(2);
MockWriter mockWriter = new MockWriter();
mockWriter.addExpectedWritelnValues("DEF");
mockWriter.setExpectedWritelnCalls(1);
Copier copier = new Copier(mockReader, mockWriter);
copier.copy();
mockReader.verify();
mockWriter.verify();
}
7/7/2015
Presented by Ernest Hill
[email protected]
20
Unit test results
===================================================
Errors logged for the 'CopierTest' test:
No errors.
===================================================
Failures logged for the 'CopierTest' test:
Total failures: 1
Test case 'testCopy(CopierTest)' failed with 'Writer WritelnParameter0Values Writer
WritelnParameter0Values added item does not match
Expected: DEF
Received: ABC'
at CopierTest.testCopy(CopierTest.java:40)
===================================================
Summary of 'CopierTest' test:
Result: Failed
Run:
1
Failures: 1
Errors:
0
Elapsed time: 0.07
7/7/2015
Presented by Ernest Hill
[email protected]
21
Unit Test with EasyMock
public void testCopy(){
MockControl mockReaderControl = EasyMock.controlFor(Reader.class);
Reader mockReader = (Reader) mockReaderControl.getMock();
mockReader.readln();
mockReaderControl.setReturnValue("ABC", 1);
mockReaderControl.setReturnValue(null, 1);
mockReaderControl.activate();
MockControl mockWriterControl = EasyMock.controlFor(Writer.class);
Writer mockWriter = (Writer) mockWriterControl.getMock();
mockWriter.writeln("DEF");
mockWriterControl.setVoidCallable(1);
mockWriterControl.activate();
Copier copier = new Copier(mockReader, mockWriter);
copier.copy();
mockReaderControl.verify();
mockWriterControl.verify();
}
7/7/2015
Presented by Ernest Hill
[email protected]
22
Results of Unit Test with
Easy Mock
===================================================
Errors logged for the 'CopierTest' test:
No errors.
===================================================
Failures logged for the 'CopierTest' test:
Total failures: 1
Test case 'testCopy(CopierTest)' failed with 'EasyMock for interface Writer:
Unexpected method call writeln("ABC")'
at CopierTest.testCopy(CopierTest.java:60)
===================================================
Summary of 'CopierTest' test:
Result: Failed
Run:
1
Failures: 1
Errors:
0
Elapsed time: 0.181
7/7/2015
Presented by Ernest Hill
[email protected]
23
Throwing an exception
public void testCopy() {
MockControl mockReaderControl = EasyMock.controlFor(Reader.class);
Reader mockReader = (Reader) mockReaderControl.getMock();
mockReader.readln();
mockReaderControl.setThrowable(new Error("Test Exception"), 1);
mockReaderControl.activate();
MockControl mockWriterControl = EasyMock.controlFor(Writer.class);
Writer mockWriter = (Writer) mockWriterControl.getMock();
mockWriter.writeln("DEF");
mockWriterControl.setVoidCallable(1);
mockWriterControl.activate();
Copier copier = new Copier(mockReader, mockWriter);
try {
copier.copy();
fail("copier.copy() should have thrown an exception");
} catch ( Error err ) {
assertEquals("err.getMessage() returned wrong text", "Test Exception", err.getMessage());
}
mockReaderControl.verify();
mockWriterControl.verify();
}
7/7/2015
Presented by Ernest Hill
[email protected]
24
Results of Unit Test with
Exception
===================================================
Errors logged for the 'CopierTest' test:
No errors.
===================================================
Failures logged for the 'CopierTest' test:
Total failures: 1
Test case 'testCopy(CopierTest)' failed with 'EasyMock for interface Writer: Expectation
failure on verify:
method call writeln("DEF"): calls expected: 1, received: 0'
at CopierTest.testCopy(CopierTest.java:87)
===================================================
Summary of 'CopierTest' test:
Result: Failed
Run:
1
Failures: 1
Errors:
0
Elapsed time: 0.17
7/7/2015
Presented by Ernest Hill
[email protected]
25
What this means
7/7/2015
Object Mocking is an invaluable
technique for improving the overall
quality of your unit tests.
Presented by Ernest Hill
[email protected]
26
Resources
www.mockobjects.com
www.mockmaker.org
www.easymock.com
EasyMock: Dynamic Mock Objects for JUnit see
www.xp2002.org/atti/TammoFreese--EasyMock.pdf
Automatically Generating System Mock Objects http://www.xpuniverse.com/2001/pdfs/Testing04.pdf
Test flexibly with AspectJ and mock objects –
www-106.ibm.com/developerworks/java/library/jaspectj2/?open&l=007,t=gr
MockDoclet – http://joe.truemesh.com/mockdoclet
7/7/2015
Presented by Ernest Hill
[email protected]
27