Unit testing means testing a class in isolation. To be able to do this any collaborator must at least be replaced by some kind of stub implementation of it. While this is definitely a good thing and appropriate in some cases it is really awkward if you have many collaborators and if these collaborators have a rather large number of methods.
Another problem with stubs is that they are not flexible enough to meet every use case, especially the special ones that hardly ever occur (except you spent hours programming the stub).
Thus you need a more general and dynamic approach.
The solution is: Mock Objects.
Mock objects also take unit testing a step further. You do not just create a stub that acts as if it were real, you also verify that the class under test collaborates with the mock object in the expected way. That means for example that the class under test calls certain methods with certain arguments on the mock object.
To work efficiently with mock objects you of course need a framework that gives you the ability to create mock objects and work with them easily.
This article is about such a framework that is based on the approach the EasyMock Framework uses. So, if you have ever worked with easymock (it’s for Java) you should have no problem working with this one. The basic workflow is as follows:
Create a mock control for a specific class or interface, get the mock object from it, set your expectations, set the behavior of the mock object, switch to replay state, use the mock object as if it were a normal instance of your class and verify if all expectations have been met.
While this sounds a little complicated and awkward at first sight it really is not. Just take a look at the following demonstration:
-
import org.as2lib.test.mock.MockControl;
-
-
// create mock control for class MyClass
-
var myMockControl:MockControl = new MockControl(MyClass);
-
// receive the mock object (it is in record state)
-
var myMock:MyClass = myMockControl.getMock();
-
// expect a call to the setStringProperty-method with argument ‘myString’.
-
myMock.setStringProperty("myString");
-
// expect calls to the getStringProperty-method
-
myMock.getStringProperty();
-
// return ‘myString’ for the first two calls
-
myMockControl.setReturnValue("myString", 2);
-
// throw MyException for any further call
-
myMockControl.setDefaultThrowable(new MyException());
-
// switch to replay state
-
myMockControl.replay();
-
-
// the class under test calls these methods on the mock
-
myMock.setStringProperty("myString");
-
myMock.getStringProperty();
-
myMock.getStringProperty();
-
-
// verify that alle expectations have been met
-
myMockControl.verify();
If any expectation has not been met an AssertionFailedError gets thrown that explains what went wrong. In the above case no AssertionFailedError should be thrown because every expectation has been met but it hadn’t if we had called the getStringProperty-method only once on the myMock-mock.
There is much more that can be done with the framework but just refer to the api documentation that is included in the download (I generated it with the old version of as2api because the new does not work and it is thus a little complex. It may be clearer to open the as-file directly and take a look at the documentation there.).
