Static Types Hinder Testing

From DavidThomasOnTheBenefitsOfDynamicTyping:

[With dynamic types, w]e gain substantial testability. You can construct mock objects very, very easily, and test out code with far less overhead. You can test objects before the classes they rely on are finished (or even started). This ability to test partial classes also lends itself to easier incremental testing.


''In some cases it can be hard to create Mock Objects to represent types in a complex external library. The most difficult aspect is usually the discovery of values and structures for parameters that are passed into the domain code. In an event-based system, the object that represents an event might be the root of a graph of objects, all of which need mocking up for the domain code to work. This process can be costly and sometimes must be weighed against the benefit of having the unit tests. However, when only a small part of a library needs to be stubbed out, Mock Objects is a useful technique for doing so. One important point that we have learned from trying to retrofit Mock Objects is that, in statically typed languages, libraries should define their APIs in terms of interfaces rather than classes so that clients of the library can use such techniques. We have used Mock Objects in the context of several application server environments and have sometimes found that the use of Java visibility modifiers, without corresponding public interfaces, makes unit testing more difficult to set up, although not impossible. For example, we were able to extend VisualAge because the tool API was written in terms of interfaces, whereas the Vector class in Java 1.1.x has many final methods but no interface, making it impossible to substitute.''


This last quote says nothing derogatory about static typing and testing. It says that non-subclassable classes are difficult to mock, but this isn't related to static typing. Consider SmallTalk's Symbol and SmallInteger, or the Smalltalk idiom of burning new with messageNotUnderstood. In object-oriented programming, all object interactions are defined in terms of interfaces, even with dynamically-typed languages. The difference is that verification of the existence of the interface is done at runtime instead of compile time. This allows for more flexibility, say by only implementing interface atoms that are necessary for the task, but this can be done in statically typed languages too. Consider stubbing and CeePlusPlus's templates.

The main difficulty in creating MockObjects in statically-typed languages is not that you need a common base class to define the interface you wish to test, but that you have to replace the slot with an indirect reference instead of a direct instance. Consider this alternate solution available in C++.

 // foo.h -- Defines the foo class which does bar and baz.

#ifndef FOO_H_ #define FOO_H_

#ifndef TEST

class foo { public: bar(); baz(); protected: private: };

#else // TEST

// Mock object. We only really need bar() for testing purposes. class foo { public: bar(); protected: private: };

#endif // TEST #endif // FOO_H_

In Java, the alternate solution is to change the CLASSPATH during testing to load a Mock jar instead of the release jar. -- SunirShah


CategoryLanguageTyping


EditText of this page (last edited August 6, 2014) or FindPage with title or text search