Naked Objects
By Richard Pawson and Robert Matthews

Writing tests

Simulations using mock views

The Naked Objects testing framework makes use of three types of mock view, corresponding to the classes, the objects, and the object's fields, each simulating what can be done using the graphical interface. Thus objects can be dragged, dropped and right-clicked, and value objects edited. All of these view classes are part of the org.nakedobjects.testing package.

Class views

Class views are created by the test framework as each class is registered. Once a ClassView is retrieved it can be used to create new instances and access existing ones.

  • public View newInstance() returns a new instance of the type represented by the ClassView. This method is a substitute for all the ways of creating an object, such as selecting the New Instance... option or dragging the class icon onto the desktop.
  • public View instances() returns a collection of the instances as would be generated by the Instances... option.
  • public View findInstance(String pattern) returns the first instance found of the represented type whose title matches, in whole or in part, the text in pattern. This mimics the various ways a user might find and then select an instance based on its title alone. This would include selecting an icon that already exists on the desktop, or searching manually through the collection of instances returned by the class menu Instances... option.
  • public View drop(DragView draggedObject) takes a dragged object and invokes the class action... method for that object's type. This corresponds to dropping an object onto the class icon.

The following code simulates three class actions: the creation of a Location object; the retrieval of a Customer object with 'Pawson' in the title; and the dropping of a customer object onto the Bookings class icon.

View location = getClassView("Locations").newInstance();

View customer = getClassView("Customers").findInstance("Pawson");

View booking = getClassView("Bookings").drop(customer.drag());
Object views

Once an object is available through a view then all the gestures that are available to the user through the graphical user interface (such as dragging and dropping, or right-clicking and selecting a menu action) can be mimicked.

  • public View rightClick(String optionName) simulates the right-clicking of an object and the selection of the named menu option. The supplied name should be the name of the action as would be seen by the user, not the method name (for example, "Return Booking" for the method actionReturnBooking). This call checks the associated about... method, if there is one, before calling the action... method. If the about... method disallows the option (i.e. it is disabled and would be shown as a grey menu option) then an IllegalActionError is thrown. If the method returns an object then this is placed in a new View before being returned.
  • public DragView drag() imitates the drag part of a drag and drop gesture. This generates a DragView object that can be accepted by the drop... methods. The DragView objects may seem superfluous but were introduced to facilitate the documentation of these gestures (as described in the next section).
  • public View drop(DragView dropObject) imitates the drop part of a drag and drop gesture. This accepts a view generated as a DragView object and invokes the relevent action method for that type of object. The associated about... method, if it exists, is called before the action... method is called, throwing an IllegalActionError if the action is disabled (in which case the drop zone flashes red). As before, this method will also place any returned object into a new View.

The following two lines of code simulate selecting the Return Booking... option on a booking object, and the dropping of one location instance onto another:

View returnBooking = booking.rightClick("Return Booking");

View newBooking = location.drop(fromLocation.drag());
Collections

If the object in the view is an internal collection rather than a business object then use the method public View select(String title) to select the first instance whose title matches, in whole or in part, the pattern in title. This mimics the user selecting an object from a list, scrolling through it if necessary.

Fields within an object view

An object view also has a series of methods that allow its fields to be set or accessed. For value fields, when a string is provided, it will be parsed by the value object. For association fields, these methods mimic the dropping of other objects and the dragging of icons. When any of these methods are invoked with an invalid field name, an IllegalActionError will be thrown.

  • public void fieldEntry(String fieldName, String entry) sets up the specified field using the entry string. The entry has to be understood by the value object and must be entered in exactly the same way that a user would enter it - that is, it must be entered in the correct format.
  • public void drop(String fieldName, DragView dropObject) attempts to set the named field so it references the object contained in the dropped view. This will invoke the appropriate set... or associate... method, or will access the collection if it is a one-to-many association, and add the item. An IllegalActionError will be thrown if the object is of the wrong type or the field already contains a reference.
  • public void removeReference(String fieldName) removes the existing reference from the specified field.
  • public void removeReference(String fieldName, View object) removes the existing reference, which matches the specified view's object, from the specified field that uses an internal collection.
  • public DragView drag(String fieldName) creates a DragView which references the object held by the named field.
  • public DragView drag(String fieldName, String title) creates a DragView which references the first object within the internal collection held by the named field that matches, in whole or in part, the text specified in title. An IllegalActionError will be thrown if the collection does not contain an item with the specified title.

The following example sets up the First Name and Last Name fields in a customer object, drops a location object into the Locations list, and drags out the Airport location object from the same list and drops it into the booking's Pick Up field:

customer.fieldEntry("First Name", "Richard");
customer.fieldEntry("Last Name", "Pawson");

customer.drop("Locations", location.drag());

booking.drop("Pick Up", customer.drag("Locations", "Airport"));