SevenMock is a light-weight Java dynamic mock objects framework. It is unusual in that it places responsibility for verifying operation parameters directly on the unit test code. This enables the test designer to write very clear, precisely targeted tests and makes test failures easier to diagnose. Download SevenMock-2.1.0.zip (2008-06-17) (Requires Java 1.5 or later)Download SevenMock-1.1.zip (2008-03-11) SevenMock on SourceForge Mock object frameworks create instances of mock objects that can be used in place of the real thing for unit testing. This enables a component to be tested in isolation even if it has dependencies on other components. The mock object is invoked by the component/object under test and supplies a pre-determined response. In addition, most mock objects are able to test the detail of method calls made to it e.g. for sequence and parameter values. Where this is not necessary, the mocks are sometimes referred to as 'stubs'. To read about other Mock Objects implementations, see http://en.wikipedia.org/wiki/Mock_object SevenMock works in a similar way to other Java dynamic mock object frameworks - by generating objects (using Java dynamic proxies) at the request of a unit test, that can be directly substituted for the real thing. The difference between SevenMock and other mock object frameworks is in the way that expectations are specified and executed - with SevenMock, the expected operation is specified by using an anonymous inner class that acts as a listener. When an operation is invoked on the mock object, SevenMock calls back to the test. The framework verifies that the correct operations are invoked in the correct order, but it is then the responsibility of the test to make whatever checks are necessary on the operation parameters. This has the following advantages:
On the negative side, the anonymous class mechanism means that it is not possible to directly mock interfaces or abstract classes. The work-around for this is to use an IDE to create an adapter class (i.e. a class with empty implementations of all abstract operations) for the interface. The diagram below shows the relationship between the test, SevenMock and the code being tested. The test sets up expectations by calling the MockControl.expect() method, passing an anonymous inner 'listener' class. This inner class extends the class being mocked and overrides a single method - the one that is expected to be called. When the test is run, the Mock ensures that this method is invoked in place of the original, which enables the developer to make any necessary assertions on the parameters passed in. The code example below shows a test asserting that the method FundsTransferManager.transferMoney() in turn calls AccountManager.deductFunds() and AccountManager.depositFunds(). Normally the setup of the mock would be performed in the test's constructor or setUp method for convenience - see SevenMockTest.java in the distribution archive for an example. public void testMoneyTransfer() { MockController mockControl = new MockController(); AccountManager acntMgrMock = mockControl.getMock(AccountManagerImpl.class); // Create an AccountManager mock FundsTransferManager ftMgr = new FundsTransferManager(acntMgrMock); // Use dependency injection to make sure the mock is used mockControl.expect(new AccountManagerImpl() { // Expect the AccountManager.deductFunds() method to be called public void deductFunds(int acntNum, int amount) { assertEquals(ACNT_NUM_1, acntNum); // Perform assertions on the parameters assertEquals(AMOUNT, amount); } }); mockControl.expect(new AccountManagerImpl() { // Expect the AccountManager.depositFunds() method to be called public void depositFunds(int acntNum, int amount) { assertEquals(ACNT_NUM_2, acntNum); // Perform assertions on the parameters assertEquals(AMOUNT, amount); } }); ftMgr.transferMoney(AMOUNT, ACNT_NUM_1, ACNT_NUM_2); // Invoke transferMoney(), passing constants as parameters mockControl.verify(); // Tell the MockControl that the test has finished } Unequenced ExpectationsExpectations created with the expect() operation are assumed to occur in strict sequence. SevenMock will verify the sequence that calls are received in and will throw an UnexpectedOperationError if expectations are encountered out of sequence. Additionally, SevenMock allows developers to specify expectations that have no implied sequence using the expectAtAnyTime() operation, or to mix sequenced and unsequenced expectations. In the latter case, SevenMock will attempt to match sequenced expectations first, checking the unsequenced expectations only if no match is found. The full list of expectation operations supported by SevenMock is as follows: How it WorksSevenMock 2.0 works with Java 1.5 and later. Users of older Java versions should use SevenMock 1.1. See also:
AcknowledgementsSevenMock was originally developed by Colin Cassidy on 7irene time as part of the test platform for their Archetype development product suite. 7irene was acquired by Prolifics in 2007. SevenMock has been used by 7irene and Prolifics on a number of client consultancy engagements and development projects. I would like to thank my colleagues at 7irene for their help and feedback and for allowing me to make SevenMock open source software. I would also like to thank SourceForge user adrianshum for his help and suggestions. Mock Objects Resources
|