Académique Documents
Professionnel Documents
Culture Documents
714
4. Issues in Teaching Interface-Based Design object under test. They are lightweight, controllable
replacements for real objects [7-11]. Using mock objects,
Teaching object-oriented design in software engineering one can test an object in true isolation. Meszaros [14]
and design courses with focus on interfaces is very defines mocks as objects that are “pre-programmed with
important for reasons discussed earlier. Students learn to expectations which form a specification of the calls they
develop systems that are loosely coupled and have less are expected to receive. They can throw an exception if
implementation dependencies. The resulting systems are they receive a call they don't expect and are checked
more flexible, extensible, and pluggable [2]. Students can during verification to ensure they got all the calls they
learn to focus on interfaces to objects they need in their were expecting”.
solution without bogged down with the implementation
details. Astels [1] lists several uses for mock objects that go
beyond using them as replacement objects for
However, there are challenges to getting students to collaborators of an object during unit testing. The uses of
successfully define and use interfaces in their projects. mocks that are most relevant to us are – mocks for
There are several reasons for this. In general CS1 and nonexistent classes or to defer implementation to later
CS2 courses do not cover interfaces to sufficient depth for time, promoting interface-based design, refining
students to truly appreciate their use and the benefits of interfaces, encouraging composition over inheritance with
programming to interfaces. Students learn about interfaces, and unit testing in isolation from the rest of the
interfaces superficially on a need-basis in CS1 and CS2 system. Mocks are easiest to use if you adopt interface-
courses mostly during the following cases: when learning based design and adhere to the principle of program to an
about event listener interfaces and event listener classes interface, not an implementation. If we don’t depend on
they have to implement in GUI programming, when concrete implementations and commit to interfaces
implementing the java.lang.Comparable and instead, we can substitute a mock object for a real object
java.util.Comparator interfaces, and when dealing with as long as the mock object provides the same interface as
the Collections Framework in Java. the real object. Next section in the paper describes how
we can get students to observe interface-based design by
Students in introductory software engineering and design requiring students to use mock objects for unit testing. It
courses will have to be taught and even required to define is not that developing interface-based design depends on
and use interfaces in systems they design to build mocks, but using mocks in software development forces
interface-based systems. One way to enforce interface- one to develop code that is interface-based, loosely
based design is to require the use of mock objects for unit coupled, and where object composition via interfaces is
testing each class in true isolation. Use of mock objects favored. These benefits are reason enough to require the
forces the students to design, from up-front, each class use of mock objects in software engineering and design
where methods (including constructors) operate on courses.
interfaces instead of concrete classes. The resulting design
will automatically be interface-rich and unit testing In the rest of this section, we describe how to use
classes in isolation becomes possible. As will be seen EasyMock and JUnit to write unit tests for
later, the use of mock objects also addresses another DecimalToBinary class that has one collaborator, an
important principle [2,3] of reusable object-oriented object that implements the IStack interface. EasyMock is
design – Design with composition, rather than a library that provides an easy to use API to generate
inheritance. Mock objects and mock-object generators are mock objects for given interfaces [12]. Using EasyMock,
discussed next. you can generate mock objects for collaborators of an
object under test (called domain code) and associate the
5. Mock Objects mock objects with domain code. JUnit is a testing
framework to write and run repeatable unit tests [13].
An object-oriented program is a web of collaborating
The UML [5] class diagram in Figure 1 shows the classes
objects that send messages to each other to accomplish
involved in the decimal to binary number conversion
something [9]. In most non-trivial code, any given object
program and their relationships. The convert() method in
may rely on several other objects that are its collaborators.
the DecimalToBinary class takes one integer value, uses a
In unit testing, the goal is to test a class in true isolation.
stack object (real or mock) to convert an integer to a
However, it is hard to test an object that has many
corresponding binary number, and returns a string
collaborators in true isolation. At the same time, it is often
representing that binary value. The required collaborator
difficult, inefficient, or even impractical to instantiate the
object (i.e., an object implementing the IStack interface)
collaborators of a class under test. A mock object is a
is passed in as a parameter to the constructor in the
replacement for a real object that is a collaborator of the
DecimalToBinary class. It is important to note that the
715
collaborators of a class under test (DecimalToBinary, in @Before
our case) are explicitly passed in as parameters to either to public void setUp() {
the constructor or relevant set methods. mock = (IStack<Integer>)
createMock(IStack.class); // 1
In EasyMock, mock objects are generated dynamically at decToBin = new
runtime. It features a “record and replay” style of usage. DecimalToBinary(mock); // 2
In the record state (before calling replay), the mock object }
does not behave like a mock object, but it simply records
expected method calls and return values. During the
replay mode, it behaves like a mock object, checking @Test // a JUnit test case method
whether expected method calls are really made. The public void testConvert() {
common coding style or usage pattern for working with try {
mock objects is: 1) create a mock object for the desired checkOrder(mock,true);
interface, 2) associate the mock object with the domain // set expected calls – step 3
object as a parameter either to the constructor or a mock.push(1);
relevant set method, 3) specify expected calls and expectLastCall().times(3);
corresponding return values (during this stage, the mock expect(mock.empty()).andReturn(
object simply records expected calls), 4) switch the mock false);
object into replay mode, 5) exercise the functionality of expect(mock.pop()).andReturn(1);
domain code (the unit under test), 6) verify expected expect(mock.empty()).andReturn(
result of the domain code by asserting any postconditions, false);
and 7) finally verify that the mock object was used expect(mock.pop()).andReturn(1);
correctly. expect(mock.empty()).andReturn(
false);
expect(mock.pop()).andReturn(1);
expect(mock.empty()).andReturn(
true);
replay(mock); // 4
String actualResult =
decToBin.convert(7); // 5
assertEquals("111",
actualResult); // 6
verify(mock); // 7
} catch (EmptyStackException ex){}
}
716
The EasyMock tool provides many other features to implementation details, define and refine these interfaces
create mocks, set expected calls and returns values, and before building concrete classes, and continue to make
verify the expected behavior. The EasyMock tool progress in system development even when the required
documentation [12] provides detailed information on how concrete classes are not available yet. This might be the
to create and use mock objects [12]. case when the required class is being developed by
another student in a team-based project. Students working
6. Teaching Interface-Based Design with with interfaces will be able to make sufficient progress
Mock Objects and get their code to compile using interfaces without the
need for the actual classes. Of course, when it is time to
This section describes how the use of mock objects execute, one must have the concrete classes that
encourages (or requires) students to develop interface- implement the required interface(s). By enforcing these
based systems. According to Gamma et al. [3], a good two design constraints, the student teams effectively
object-oriented design adheres to two key principles – 1) develop software that adheres to the key object-oriented
program to an interface, not an implementation, and 2) design principle – program to an interface, not an
favor object composition over class inheritance. A design implementation.
process that observes these two principles yields object-
oriented designs that are loosely coupled, flexible, Design requirement 3 forces students to use object
extensible, and pluggable and promotes black-box reuse. composition and delegation as means for reusing existing
Now the challenge is how to get students to actively functionality. The resulting software will adhere to the
employ these principles while designing an object- other key object-oriented principle – favor object
oriented system? composition over class inheritance. In addition, the design
requirement 3 observes the Law of Demeter by explicitly
One approach to getting students to observe these passing in the collaborating objects when an object is
principles while designing is to specify few simple design created or immediately after. This is really required when
requirements (constraints) by the instructor as described working with mock objects because a mocked
below and strictly enforce these requirements during implementation can be substituted for the neighboring
review and project evaluations. (collaborating) objects for the object under test.
717
and principles that should be taught in every software 11. Dave Thomas and Andy Hunt, Mock Objects, IEEE
engineering curriculum, especially in introductory courses Software, May/June 2002.
in software engineering and design. 12. EasyMock 2.4 tool and documentation, available
from http://easymock.org/
7. Conclusions 13. JUnit 4.x tool and documentation, from
http://junit.org/
In this paper, we attempted to show how mock objects 14. Gerard Meszaros, xUnit Test Patterns: Refactoring
can be used to enforce the development of interface-based Test Code, Addison-Wesley, 2007, ISBN
system in software engineering and design courses. A 0131495054.
good object-oriented design will adhere to two key 15. Karl Lieberherr and Ian Holland, Assuring Good
principles – program to interfaces instead of concrete Style for Object-Oriented Programs, IEEE Software,
classes, and favor object composition over class September 1989, pp 38-38.
inheritance. The role of unit testing is also critical to the
development of quality code. By using mock objects,
students can not only test their units in isolation, but also
develop code that adheres to the two key principles of
reusable object-oriented design mentioned above.
Therefore, it is important to teach interface-based design
in software engineering courses and mock objects provide
an indirect path to that end result.
8. References
1. David Astels, Test-Driven Development – A Practical
Guide, The Coad Series, Prentice Hall, 2003, ISBN
0-13-101649-0.
2. Peter Coad, Mark Mayfield, and Jonathan Kern, Java
Design: Building Better Apps and Applets, Yourdon
Press Computing Series, Prentice Hall, 2nd edition,
1999, ISBN 0-139-11181-6.
3. Erich Gamma, Richard Helm, Ralph Johnson, and
John Vlissides, Design Patterns – Elements of
Reusable Object-Oriented Software, Addison
Wesley, 1995, ISBN 0-201-63361-2.
4. Martin Fowler, Refactoring – Improving the Design
of Existing Code, Addison Wesley, 1999, ISBN 0-
201-48567.
5. Grady Booch, James Rumbaugh, and Ivar Jacobson,
The Unified Modeling Language User’s Guide,
Addison Wesley, 1999, ISBN 0-201-57168-4.
6. Peter van der Linden, Just Java 2, Sun Microsystems
Press, Sixth edition, 2004, ISBN 0-13-148211-4.
7. Alexander Chaffee and William Pietri, Unit testing
with mock objects, IBM developerWorks, November
2002.
8. Tammo Freese, EasyMock: Dynamic Mock Objects
for JUnit, http://www.agilealliance.org/system/
article/file/975/file.pdf
9. Steve Freeman, Tim Mackinnon, Nat Pryce, and Joe
Walnes, Mock Roles, Not Objects, available from
http://mockobjects.com/
10. Tim Mackinnon, Steve Freeman, and Philip Craig,
Endo-Testing: Unit Testing with Mock Objects,
available from http://mockobjects.com/
718