[PDF] [PDF] Mock Roles, not Objects - jMock

called “interface discovery” We have also reimplemented our framework to support dynamic generation of Mock Objects, based on this experience The rest of 



Previous PDF Next PDF





[PDF] Using Class Interfaces and Mock Objects to Unit Test Aspects - CORE

This was accomplished by having the mock object inherit from the same interface as the base code, so that the mock object could be swapped in for the aspect



[PDF] JUnit Présentation des mocks - Cedric-Cnam

dépendance en construisant une interface intermédiaire faisant reposer uniquement sur des interfaces outils-java/tests-performance/test-junit-mock/



[PDF] Test logiciel et Mocks - LIRMM

25 sept 2018 · Doublures de test, Mockito et PowerMock Mockito Spécification du comportement du mock Cas d'une méthode avec paramètres 1 interface



[PDF] Tests orientés objets Junit, Mockito

Comme les tests unitaires u0lisent l'interface de l'unité à tester, ils amènent le développeur Mock = Objet fac0ce • les mocks (ou Mock object) sont des objets



[PDF] Mock Roles, not Objects - jMock

called “interface discovery” We have also reimplemented our framework to support dynamic generation of Mock Objects, based on this experience The rest of 



[PDF] Tests unitaires, Junit, Mockito

Un mock a la même interface que l'objet qu'il simule • L'objet client ignore s'il interagit avec un objet réel ou un objet simulé • La plupart des frameworks de 



[PDF] Mockito pour Java - Formations en Informatique de Lille

Création d'un mock Carte est une interface (SVL) ou une classe Carte carte = mock(Carte class); le mock n'est pas nommé dans les messages d'erreurs, ou

[PDF] mock roles

[PDF] mocktail menu pdf

[PDF] mocktail pdf

[PDF] mocktail recipes pdf

[PDF] mod congruence calculator

[PDF] mode d'emploi telecommande came top 432na

[PDF] mode d'emploi telecommande clim toshiba inverter

[PDF] mode d'emploi telecommande fujitsu atlantic

[PDF] mode d'emploi télécommande fujitsu inverter ar rah1e

[PDF] mode d'emploi telecommande sfr box

[PDF] model 5200 garage door

[PDF] model a2200 ipad case

[PDF] model condo rules and regulations

[PDF] model question paper 2020

[PDF] model question paper for 10th

Mock Roles, not Objects

Steve Freeman, Nat Pryce, Tim Mackinnon, Joe Walnes

ThoughtWorks UK

Berkshire House, 168-173 High Holborn

London WC1V 7AA

{sfreeman, npryce, tmackinnon, jwalnes} @thoughtworks.com

ABSTRACT

Mock Objects is an extension to Test-Driven Development that supports good Object-Oriented design by guiding the discovery of a coherent system of types within a code base. It turns out to be less interesting as a technique for isolating tests from third-party libraries than is widely thought. This paper describes the process of using Mock Objects with an extended example and reports best and worst practices gained from experience of applying the process. It also introduces jMock, a Java framework that embodies our collective experience.

Categories and Subject Descriptors

D.2.2 [Software Engineering]: Design Tools and Techniques,

Object-Oriented design methods

General Terms

Design, Verification.

Keywords

Test-Driven Development, Mock Objects, Java..

1. INTRODUCTION

Mock Objects is misnamed. It is really a technique for identifying types in a system based on the roles that objects play. In [10] we introduced the concept of Mock Objects as a technique to support Test-Driven Development. We stated that it encouraged better structured tests and, more importantly, improved domain code by preserving encapsulation, reducing dependencies and clarifying the interactions between classes. This paper describes how we have refined and adjusted the technique based on our experience since then. In particular, we now understand that the most important benefit of Mock Objects is what we originally called "interface discovery". We have also reimplemented our framework to support dynamic generation of Mock Objects, based on this experience. The rest of this section establishes our understanding of Test- Driven Development and good practice in Object-Oriented Programming, and then introduces the Mock Object concept. The

rest of the paper introduces Need-Driven Development, as expressed using Mock Objects, and shows a worked example.

Then we discuss our experiences of developing with Mock Objects and describe how we applied these to jMock, our Mock

Object framework.

1.1 Test-Driven Development

In Test-Driven Development (TDD), programmers write tests, called Programmer Tests, for a unit of code before they write the code itself [1]. Writing tests is a design activity, it specifies each requirement in the form of an executable example that can be shown to work. As the code base grows, the programmers refactor it [4], improving its design by removing duplication and clarifying its intent. These refactorings can be made with confidence because the test-first approach, by definition, guarantees a very high degree of test coverage to catch mistakes. This changes design from a process of invention, where the developer thinks hard about what a unit of code should do and then implements it, to a process of discovery, where the developer adds small increments of functionality and then extracts structure from the working code. Using TDD has many benefits but the most relevant is that it directs the programmer to think about the design of code from its intended use, rather than from its implementation. TDD also tends to produce simpler code because it focuses on immediate requirements rather than future-proofing and because the emphasis on refactoring allows developers to fix design weaknesses as their understanding of the domain improves.

1.2 Object-Oriented Programming

A running Object-Oriented (OO) program is a web of objects that collaborate by sending messages to each other. As described by Beck and Cunningham [2], "no object is an island. ... All objects stand in relationship to others, on whom they rely for services and control". The visible behaviour of each object is defined in terms of how it sends messages and returns results in response to receiving messages.

Figure 1. A Web of Collaborating Objects

The benefit of OO is that it defines a unit of modularity which is internally coherent but has minimal coupling to the rest of the system. This makes it easy to modify software by changing how Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. To copy otherwise, or republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Conference"04, Month 1-2, 2004, City, State, Country.

Copyright 2004 ACM 1-58113-000-0/00/0004...$5.00.

objects are composed together into an application. To achieve this flexibility in practice, objects in a well-designed system should only send messages to their immediate neighbours, otherwise known as the Law of Demeter [15]. Note that the immediate neighbours of an object do not include objects whose references are returned from a call to another object. Programmers should avoid writing code that looks like: dog.getBody().getTail().wag(); colloquially known as a "Train Wreck". This is bad because this one line depends on the interfaces and implied structure of three different objects. This style laces structural dependencies between unrelated objects throughout a code base. The solution is described by the heuristic "Tell, Don"t Ask" [7], so we rewrite our example as: dog.expressHappiness(); and let the implementation of the dog decide what this means. Given an object that talks only to its immediate neighbours, we can describe it in terms of the services it provides and the services it requires from those neighbours. We call those required services outgoing interfaces because that is how the object calls out to other objects.

1.3 Test-Driven Development of Object

Oriented Programs

If we concentrate on an object"s external interactions, we can test it by calling one of its services and tracking the resulting interactions with its neighbours. If we are programming test-first, we can define those tests in terms of outgoing interfaces (which might not yet exist) because that"s how we can tell whether an action has succeeded. For example, we decide that dog.expressHappiness() has succeeded when its implementation has called body.wagTail(). This is a design decision that we make when developing the dog object about how to implement one of its services (note that we"re still avoiding a Train Wreck by not asking the body about its implementation of a tail). If the DogBody object does not yet have a wagTail() method, this test has identified a new requirement that it must fulfil. We don"t want to stop now and implement the new feature, because that would be a distraction from the current task and because the implementation of wagTail() might trigger an unpredictably long chain of further implementations. Instead we provide a false implementation of the DogBody object that pretends to implement the method. Now we can instrument that false object to see if wagTail() is actually called when testing expressHappiness(). To summarise, we test an object by replacing its neighbours with objects that test that they are called as expected and stub any behaviour that the caller requires. These replacements are called mock objects. We call the technique of TDD with mock objects,

Mock Objects.

2. MOCK OBJECTS AND NEED-DRIVEN

DEVELOPMENT

Mock Objects changes the focus of TDD from thinking about the changes in state of an object to thinking about its interactions with other objects. We use Mock Objects to let us write the code under test as if it had everything it needs from its environment. This process shows us what an object"s environment should be so we can then provide it.

2.1 Need-Driven Development

A core principle of Lean Development is that value should be pulled into existence from demand, rather than pushed from implementation: "The effect of 'pull" is that production is not based on forecast; commitment is delayed until demand is present to indicate what the customer really wants." [16]. This is the flow of programming with Mock Objects. By testing an object in isolation, the programmer is forced to consider an object"s interactions with its collaborators in the abstract, possibly before those collaborators exist. TDD with Mock Objects guides interface design by the services that an object requires, not just those it provides. This process results in a system of narrow interfaces each of which defines a role in an interaction between objects, rather than wide interfaces that describe all the features provided by a class. We call this approach Need-Driven

Development.

For example, Figure 2 depicts a test of object A. To fulfil the needs of A, we discover that it needs a service S. While testing A we mock the responsibilities of S without defining a concrete implementation. TestA mock S S

Figure 2. Interface Discovery

Once we have implemented A to satisfy its requirements we can switch focus and implement an object that performs the role of S. This is shown as object B in Figure 3. This process will then discover services required by B, which we again mock out until we have finished our implementation of B. TestB mock T mock UST U

Figure 3. Iterative Interface Discovery

We continue this process until we reach a layer that implements real functionality in terms of the system runtime or external libraries. The end result is that our application is structured as a composition of objects that communicate through narrowly defined role interfaces (Figure 4). As another writer put it, "From each according to his abilities, to each according to his needs!" [11]. AB C E D ST U WV Figure 4. A Web of Objects Collaborating Through Roles Our experience is that systems we produce this way tend towards very flat class hierarchies. This avoids well-known problems, such as the Fragile Base Class [12], which make systems harder to understand and modify. This process is similar to traditional Top-Down Development, in which the programmer starts at the highest level of abstraction and proceeds, layer by layer, to fill in the detail. The intention is that each layer of code is written in a coherent terminology, defined in terms of the next level of abstraction. This is difficult to achieve in practice because the most important decisions have to be taken early and it is hard to avoid duplication across lower level components. TDD mitigates this by including Refactoring in its process. Programming from the Bottom-Up has different risks. All the authors have had the experience of developing a supporting class in isolation, as part of a larger task, only to find that the result was not right because we had misunderstood something. We find that Need-Driven Development helps us stay focussed on the requirements in hand and to develop coherent objects.

3. A WORKED EXAMPLE

To illustrate the technique, we will work through an example. Consider a component that caches key-based retrievals from an object loading framework. The instances become invalid a given time after they"ve been loaded, so sometimes we want to force a reload. With Mock Objects we use a common structure, identified in [10], for programmer tests.

1. Create the test fixture including any mock objects

2. Define expectations and stubs on the mock objects

3. Invoke the method to be tested

4. Verify expectations and assert any postconditions

This makes the tests easier to read.

3.1 An Object Loader

Our first programmer test should be a simple success case, to load and return objects that are not in the cache. In the case, we expect to call the loader exactly once with each key, and we need to check that the right value is returned from the cache. Using the jMock framework, described in detail later, we can write out a JUnit [9] test for this (we have left out instance creation for brevity. KEY and VALUE are constants in the test case, not part of the jMock framework). public class TimedCacheTest { public void testLoadsObjectThatIsNotCached() { // we expect to call load // exactly once with the key, // this will return the given value mockLoader.expect(once()) .method("load").with( eq(KEY) ) .will(returnValue(VALUE)); mockLoader.expect(once()) .method("load").with( eq(KEY2) ) .will(returnValue(VALUE2)); assertSame( "should be first object",

VALUE, cache.lookup(KEY) );

assertSame( "should be second object",

VALUE2, cache.lookup(KEY2) );

mockLoader.verify(); jMock uses reflection to match methods by name and parameters. The jMock syntax for defining expectation is unusual, the first expectation is equivalent to: expectation = mockLoader.expect(once()); expectation.method("load"); expectation.with( eq(KEY) ); expectation.will(returnValue(VALUE)); We daisy-chain these calls to make the tests more compact and readable; this is discussed later. The test implies that the Cache has relationships with somethingquotesdbs_dbs17.pdfusesText_23