Download presentation
Presentation is loading. Please wait.
1
Mocking Your Objects with Impunity
Ernest Hill has been developing software for over 20 years. He’s written software on a number of platforms using a multitude of languages. He’s been developing in Java for the past three years, but it’s only been in the last four months that He has become an avid practitioner of object mockery. 11/17/2018 Presented by Ernest Hill
2
Presented by Ernest Hill ernesthill@earthlink.net
Goal of Presentation 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 11/17/2018 Presented by Ernest Hill
3
Presented by Ernest Hill ernesthill@earthlink.net
Topics of Discussion What is Object Mocking? Why Mock Objects? What tools are available to support Object Mockery 11/17/2018 Presented by Ernest Hill
4
Presented by Ernest Hill ernesthill@earthlink.net
What is Object Mocking? 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 No, it’s not making fun of someone else’s code. It’s creating a mock implementation of an object that can be used as a stand-in in testing.This mock object stands-in for an object that collaborates with the object you are testing. The mock replaces domain dependencies with a mock implementations that is only used in testing. For example you might set up a mock database or a mock connection. A mock object allows you to set expectations. You set up the values to be passed to and returned by the mock object. The mock object lets you verify that the expectations were met. The mock object can examine the parameters it was passed and verify that it received the expected values. 11/17/2018 Presented by Ernest Hill
5
Why engage in Object Mocking?
The real object has behaviour that is hard to cause or is non-deterministic 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 Why engage in Object Mocking? The real object has behaviour that is hard to cause or is non-deterministic. For example you need to make sure the object you are testing handles an exception thrown from a method invoked on another object. Sometimes it is impossible to force the exception to be thrown on the real object, but an exception can be easily thrown from a mock object. The real object is difficult to set up. Often you must manage the state of an object before using it in a test. This can be difficult if not impossible accomplish. Mock objects can make it much easier to setup state especially when testing objects that need to work with a database or network. The real object has (or is) a User Interface. Interaction with a GUI can be especially troublesome without resorting to using something like the java.awt.Robot class. Interacting with a mock object however can be much simpler. Test needs to query the object, but queries are not available. For example you need to determine if a “callback” method was invoked. Since the mock object verifies that each method was invoked as specified we can know that the “callback” was invoked. If you are engaging in Test-First development the real object may not exist. Using a mock object can aid in interface discovery, a mock object serves as a hypothesis of how an object should act. 11/17/2018 Presented by Ernest Hill
6
What tools are available to support Obect Mockery
The MockObjects framework MockMaker EasyMockt I’m going to take a brief look at three of the tools available. The MockObject framework MockMaker EasyMock After the overview will see some examples of using the tools. 11/17/2018 Presented by Ernest Hill
7
MockObjects Framework
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 MockObjects is an open source generic unit testing framework available for download at mockobjects.org. The framework provides utility tools for creating mock objects. It also provides mock implementations of common libraries such as IO, Servlets and JDBC. The website also serves as a reference point for ideas and tools for unit testing, particulary those based on MockObjects. We’ll see how MockObjects are used in our discussion of MockMaker. 11/17/2018 Presented by Ernest Hill
8
Presented by Ernest Hill ernesthill@earthlink.net
MockMaker Overview 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 MockMaker is an open source tool available at mockmaker.org. It is a passive code generation tools. Passive code generation tools are wizard like tools that generate code once. It is then up to the developer to make changes to the generated code as the project evolves. MockMaker generates objects that are built on the MockObjects framework. MockMaker has both a command line and gui interface. MockMaker can only be used to generated objects from an interface not a class. 11/17/2018 Presented by Ernest Hill
9
Presented by Ernest Hill ernesthill@earthlink.net
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 MockMaker generates methods in addition to those in the interface being mocked. 11/17/2018 Presented by Ernest Hill
10
Presented by Ernest Hill ernesthill@earthlink.net
MockMaker Drawbacks Interface being used is not directly visible If interface changes MockObject must be modified or regenerated No method to throw exceptions 11/17/2018 Presented by Ernest Hill
11
Presented by Ernest Hill ernesthill@earthlink.net
EasyMock Overview 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 Easymock is an open source tool available for download at easymock.org. Easymock takes a different approach to mock generation than MockMaker. EasyMock uses reflection to dynamically create proxies that implement the specified interface at run time. So the generation of the mock object becomes part of your unit test. EasyMock actually generates two objects at runtime, the Mock Object Mock Object which is an imiplementation of the interface to simulate and the Easy Mock Mock control which has methods for controlling its associated mock. This is actually simpler than it sounds. 11/17/2018 Presented by Ernest Hill
12
Presented by Ernest Hill ernesthill@earthlink.net
EasyMock Features 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 Easy mock allows you to specify the parameters that should be passed to a method when it is invoked on the mock object. Easy mock also allows you to specify the value to be returned from a method invocation. Easymock also allows you to specify the number of times a method should be invoked. You can also specify the number of times a method should expect a parameter or return a parameter. You can also specify that an exception should be thrown. So for example you could specify that the doit method should be called 2 times with the string ABC as a parameter and the string DEF the third time, it should return true the first two times and throw an exception the third. Finally you can use the verify method to make sure everything went as expected. 11/17/2018 Presented by Ernest Hill
13
Presented by Ernest Hill ernesthill@earthlink.net
EasyMock Drawbacks EasyMock generates objects on the fly so you can’t add any behaviour EasyMock uses the equals method to compare parameters EasyMock generates it’s mocks at runtime so there is no way to modify the behaviour other than through the provided methods. This is sufficient in most cases. Another problem may be that EasyMock uses an objects equals method to compare the expected parameter with the one that was passed from the test object. Sometimes, for example in comparing arrays this may not be what you want. 11/17/2018 Presented by Ernest Hill
14
Presented by Ernest Hill ernesthill@earthlink.net
Test Domain 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 Let’s take a look at how to use these tools. First let’s talk about what we are going to test. 11/17/2018 Presented by Ernest Hill
15
Presented by Ernest Hill ernesthill@earthlink.net
Interfaces public interface Reader { public String readln(); } public interface Writer { public void writeln(String line); Here are the interfaces we are going to generate mock objects for. 11/17/2018 Presented by Ernest Hill
16
Presented by Ernest Hill ernesthill@earthlink.net
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); Here’s the class we are going to test. 11/17/2018 Presented by Ernest Hill
17
Presented by Ernest Hill ernesthill@earthlink.net
Run MockMaker java mockmaker.MockMaker Reader > MockReader.java java mockmaker.MockMaker Writer > MockWriter.java First run the command line interface for MockMaker to generate our mock objects. 11/17/2018 Presented by Ernest Hill
18
Presented by Ernest Hill ernesthill@earthlink.net
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(); Here’s the code generated for out reader. You can see that there is a method set our return values. Also there is a method to verify that our expcectations were met. 11/17/2018 Presented by Ernest Hill
19
Presented by Ernest Hill ernesthill@earthlink.net
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(); You can see we have a method to set the expected parameters. 11/17/2018 Presented by Ernest Hill
20
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(); } Here’s a unit test using the mock objects generated by MockMaker. 11/17/2018 Presented by Ernest Hill
21
Presented by Ernest Hill ernesthill@earthlink.net
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: Failures: 1 Errors: Elapsed time: 0.07 Here are the results of the test. 11/17/2018 Presented by Ernest Hill
22
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(); } Here is an example using easy mock. You see the first thing we do is set up a control for the interface we want to mock. We then the mock object from the control. 11/17/2018 Presented by Ernest Hill
23
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: Failures: 1 Errors: Elapsed time: 0.181 Here are the results of our test. 11/17/2018 Presented by Ernest Hill
24
Presented by Ernest Hill ernesthill@earthlink.net
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(); We can set up our mock object to throw an exception. 11/17/2018 Presented by Ernest Hill
25
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: Failures: 1 Errors: Elapsed time: 0.17 Here are the results. 11/17/2018 Presented by Ernest Hill
26
Presented by Ernest Hill ernesthill@earthlink.net
What this means Object Mocking is an invaluable technique for improving the overall quality of your unit tests. I have found the use of mock objects has really improved my testing. Give them a try and see what you think. 11/17/2018 Presented by Ernest Hill
27
Presented by Ernest Hill ernesthill@earthlink.net
Resources EasyMock: Dynamic Mock Objects for JUnit see Automatically Generating System Mock Objects - Test flexibly with AspectJ and mock objects – www-106.ibm.com/developerworks/java/library/j-aspectj2/?open&l=007,t=gr MockDoclet – 11/17/2018 Presented by Ernest Hill
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.