Description

This is a rough draft of the planned API, and brief discussions of the function/intention of each method. Some of it is not implemented yet, and it is subject to change.

To see the API for the latest release, you can review the online javadoc. There is also a (done) or (partially done) note next to each item which is done or partially done.

VM - VirtualMock Main Class

  • VM (partially done) - This is the main class, with all static methods. All methods in this section are static calls on this class.
  • VMA - An alternate VirtualMock Main Class which acts as an adapter by supporting (as much as possible) the same syntax as other popular mock object frameworks, such as EasyMock, DynaMock, etc. This is meant to make it easier for users of other frameworks to migrate to VirtualMock, or use VirtualMock in conjunction with their framework.

Uninitialized Phase

  • init() (done) - VM.init() must be called before any other methods are called on VM, to ensure the VirtualMock environment is properly initialized.
  • addExclusionPattern(String exclusionPattern) - VM.addExclusionPattern() can be used to exclude packages or classes from the Aspect-Oriented "weaving" process which is the underlying mocking mechanism of VirtualMock. This may be required because some classes (such as those which use EasyMock) can cause VirtualMock to fail under some circumstances. If you are encountering a strange error, run Ant or Maven in verbose mode, try to determine which class or package is causing problems, and exclude it to see if that fixes the problem. The pattern language for defining exclusions is the same as that used by AspectWerkz for it's Join Point selection patterns. See Join point selection pattern language

Recording Phase

  • setClassUnderTest(Class classUnderTest); setClassesUnderTest(Class[] classesUnderTest) - This is optional for reporting purposes - for example - determining all calls which were made by the classUnderTest, but were not mocked. An exception should be thrown if this method is called more than once in the same test case.
  • addMockClass(Class classToMock) (done) - This tells VirtualMock that subsequent calls to this class will be intercepted by VirtualMock. This allows the "recording" of mock calls that will be expected to be called by the class under test. This is the same approach used by EasyMock. The recorded calls will later be matched against the actual calls that are made during the playback phase, and any mismatches can be reported during the verification phase. It also allows other VirtualMock functions to be performed for the class.
  • autoRecordAllCalls(Class classToMock) - This tells VirtualMock that all subsequent calls to this class will be intercepted as mock calls. This is in contract to the recordCalls() method, which requires you to explicitly record all calls. By default, these calls will have ALWAYS_MATCHER defined at the ArgMatcher for all arguments (in other words, no arguments will be verified). Also, the return value will be a GeneratedReturnValue. If the user wishes to override the behavior of any auto-recorded call, then can explicitly record the call just as the would normally, including argMatchers and return values, or even unmocking them.
  • recordReturnValue(Object objectToReturn); recordReturnValue(primitive primitiveToReturn) (done) - Specifies the return value for the last recorded call. This is mutually exclusive with recordException(), an exception should be thrown if it has already been called. If no return value is recorded, and the method returns a value, then a default value will be returned (default values for primitives, empty arrays, default constructor for objects with no-arg constructor, null (?) for objects without no-arg constructor).
  • recordGeneratedReturnValue(); recordGeneratedReturnValue(GeneratedReturnValue generatedReturnValue) - Specifies that the return value for the last recorded call should be automatically generated. This is mutually exclusive with recordException(), an exception should be thrown if it has already been called. By default, a dummy value is returned. However, the user can subclass GeneratedReturnValue to provide their own custom logic for generating return values based on the parameters (or any other criteria, or no criteria)
  • recordArgMatcher(ArgMatcher); recordArgMatchers(ArgMatcher, ArgMatcher); recordArgMatchers(ArgMatcher, ArgMatcher, ArgMatcher); recordArgMatchers(ArgMatcher[]) (done) - An argument matcher allows you to specify how strict the matching will be for an argument passed in to a mock method call. The overloaded versions are convenience methods to specify argument matchers for methods with multiple arguments. See the ArgMatcher section below for more info.
  • recordArgTypeAssignableMatching(boolean); recordArgTypesAssignableMatching(boolean, boolean); recordArgTypesAssignableMatching(boolean, boolean, boolean); recordArgTypesAssignableMatching(boolean[]) - This allows for control of how argument TYPES for invoked calls are matched against recorded calls. If true is specified for an argument, then the Java method Class.isAssignableFrom() will be used to compare the invoked argument against the recorded argument. By default, this is always false, which means that the invoked argument class must be exactly the same as the recorded argument class in order for the call to be matched. This will allow the arguments passed by invoked calls to be implementations or subclasses of the arguments which were recorded, and still match. The overloaded versions are convenience methods to specify assignable flags for methods with multiple arguments.
  • setDefaultArgMatcher(ArgMatcher) - This sets the default ArgMatcher that will be used globally for all arguments on all recorded calls, UNLESS (an) argMatcher(s) is(are) explicitly set for a call using recordArgMatcher(s)()
  • recordUnlimitedInvocations() - Allows an unlimited number of invocations to be made for the last recorded call. This does not ignore any ArgMatchers which are defined for the call - an invoked call will still only match an unlimited invocation mocked call if the ArgMatcher matches. Note that this violates the rule RECORDED_CALL_COUNT_MUST_MATCH_INVOKED_CALL_COUNT, but sometimes it may be too difficult or impossible to pre-determine the number of times a call will be invoked.
  • getLastCallSignature() - This returns the Signature for this call, which can be used to manually create a CallID to later be used in the verification phase to retrieve arguments which were passed in during the playback phase (with the getPassedParameter(...) method). The CallId is the Signature with a colon and call sequence appended. TODO: There is probably a better way than having the user manually generate a CallId String, but this works for now.
  • getLastCallId() - This returns a unique ID for this call, which can later be used in the verification phase to retrieve arguments which were passed in during the playback phase (with the getPassedParameter(...) method). The ID is the call's Signature , and an appended sequence number (for multiple calls to the same method) separated by a colon.
  • repeatLastCall(); repeatLastCall(int) - causes the last recorded call to be played back one or more times. This includes any return value or exception that was specified. An IllegalStateException should be thrown if any record*() method is invoked after this call without first recording a new call. An IllegalStateException should also be thrown if recordUnlimitedInvocations() was set for the last call (because you could never invoke a second identical call if the first one has unlimited calls!)
  • eraseLastCall(); eraseLastCall(int) - causes the last recorded call to NOT be mocked up (multiple times, if desired). In other words, VirtualMock will not intercept it, and will allow the 'real' call to be made on the class that is being mocked. This is useful if you want to mock up some calls which match a given signature, but not all of them. An IllegalStateException should be thrown if any record*() method is invoked after this call without first recording a new call. Note that this violates the rule REPLACE_EVERYTHING, and will trigger a violation of the rule (is this a good reason to make REPLACE_EVERYTHING have a WARN enforcement level instead of FAIL?). (TODO: how will this behave for all the possible types of Matchers that can be defined for the last call? Should it be invalid for some types of matchers?)
  • appendPreRecordedCalls(Call []) - Allows an array of predefined Call objects to be added to the recorded calls list. This allows the setup of commonly mocked calls or sets of calls to be abstracted out and used across multiple test cases.

Playback Phase

  • playbackCallsOrdered() - This puts all classes that were "recorded" (with recordCalls()) into "playback" mode. This means that all subsequent calls to the classes will be interpreted as invocations by the class under test. VirtualMock should return an error if any subsequent invocations are made by any class other than the class under test (this either means you turned on playback mode too early, or the call is being made indirectly by a collaborator). In playback mode, VirtualMock will match the actual invocations by the Class Under Test against the calls that were recorded. The "Ordered" version of playback indicates that all calls must be invoked in the same order in which they were recorded. The behavior of Ordered playback is also dependent on the ArgMatcher(s) that are defined for each recorded call. The currently expected call in the ordered recorded call queue is "matched" against invocations of calls with the same method signature, based on the ArgMatcher that is defined for that recorded call. In other words, if an invoked method signature is the same as the currently expected recorded method signature, it only "matches" if the ArgMatcher(s) for the recorded call all return true. This method is mutually exclusive with playbackCallsUnordered, and will throw an exception if it has already been called.
  • playbackCallsUnordered() (done) - This is the same as playbackCallsOrdered, except that the recorded calls can be invoked in any order. In other words, they do not have to be invoked in the same order in which they were recorded. The behavior of Unrdered playback is also dependent on the ArgMatcher(s) that are defined for each recorded call. Any call in the unordered recorded call queue is "matched" against invocations of any call with the same method signature, based on the ArgMatcher that is defined for that recorded call. In other words, if an invoked method signature is the same as any recorded method signature, it only "matches" if the ArgMatcher(s) for the recorded call all return true. This method is mutually exclusive with playbackCallsOrdered, and will throw an exception if it has already been called.

Verification Phase

  • verify() (partially done) - verifies that all recorded calls to all mock classes were actually called during the playback phase. Also performs reporting, statistical, and other verification tasks. By default, there will be a check triggered by the teardown method to verify that this method was called.
  • verify(Class classToVerify) - verifies a single class. Should throw an exception if no calls were recorded for this class.
  • doNotVerify(Class classToNotVerify) - disables verification of a single class.
  • ArgMatcher - See the ArgMatcher section below. The VM class will contain static class variables for all the default ArgMatcher types, for easy of use when passing in to recordArgMatchers()
  • getPassedParameter(String CallId); getPassedParameter(String CallId, int position); getPassedParameter(String CallId, int position, int sequence) - See getLastCallId(). This method retrieves a parameter which was passed to the specified call during the actual invocation of the method by the class under test. The position parameter specifies which parameter to retrieve for multiple calls. The sequence parameter will override the sequence specified on the CallId, and retrieve the specified call when there were multiple invocations of the same call. Descriptive exceptions would be thrown appropriately if the user attempts to retrieve a parameter or call which doesn't exist. This method would be useful if a user wants to perform their own "manual" verification, by directly inspecting the arguments that were passed in when the call was invoked.

Rules/Policy Settings

  • setRuleEnforcementPolicy(int rule, int enforcementLevel) - Specify how a rule will be enforced during the verification phase. Enforcement levels are IGNORE, WARN, and FAIL.
  • setGlobalRuleEnforcementPolicy(int enforcementLevel) - Set enforcement level for all rules at once (useful for disabling all warnings). Note that this will be ignored for rules which do not support the specified global enforcement level.
  • addIgnoredClass(String ignoredClass) - classes ignored when identifying non-mocked collaborators. can be package substring or fully qualified class name. By default java.util and java.lang ?
  • removeIgnoredClass(String ignoredClass - inverse of addIgnoredClass
  • setRuleEnforcementPolicies(Properties) - Allows rules and enforcement policies to be specified via a property file. TODO: Is there a better way than passing is a Properties? Should this be in a predefined location(s), like the log4j.properties file?
  • tearDown() - Aspect should detect when tearDown() method occurs, and automatically detect whether verify() was called.

Reporting

  • listRecordedCalls() - lists all Calls that have been recorded.
  • listUnmockedCalls() - lists all Calls that the Class Under Test made to unmocked collaborators (except for Ignored Classes)
  • listAllCalls - lists all Calls that the Class Under Test made to all collaborators, mocked or unmocked.

ArgMatcher Class

  • The ArgMatcher concept allows different rules to be set for matching arguments to mock methods. Implementations of ArgMatcher will be able to specify different matching rules. See the "Constraint" concept used by mockobjects.com and the "ParameterMatcher" concept used by EasyMock
  • For all ArgMatchers, the "expected" (mocked) argument is compared TO the "actual" (invoked) argument. This order is important to understand for some matchers, such as GreaterThanMatcher. For example, if a GreaterThanMatcher is defined, the match will return true if Expected (mocked) is GreaterThan Actual (invoked).
    • ArgMatcher(actual, mocked) (done) - interface for all arg matchers. Can be implemented and customized, or one of the pre-defined implementations listed below can be used. (IDEA - would it be possible to use Jakarta BeanUtils to provide a MatchBean implementation that would use reflection to perform .equals() on all properties of a bean - maybe even recursively?). The following predefined matchers will be available as constants on the VM class.
      • EqualsMatcher (done) - actual.equals(mock) returns true (default ArgMatcher)
      • AlwaysMatcher (done) - any value (null or non null)
      • ArrayMatcher - for an argument which is an array, perform .equals() on each element.
      • ListMatcher - for an argument which is a List (the interface in the Java Collections package), perform .equals() on each element.
      • GreaterThanMatcher - actual is greater than the mocked
      • LessThanMatcher - actual is less than the mocked
      • InstanceOfMatcher - actual is instanceof the mocked
      • SameMatcher - actual is same object as the mocked

Call Class

object which encapsulates all information about an expected call which will be mocked, including the signature, expected arguments, argument matching rules, return values, and exceptions

GeneratedReturnValue

object which represents an automatically generated return value. There is default behavior to do some "smart" generation of return values, or it can be overridden to provide custom behavior.

  • generate(Class returnType, Object[] argValues) - Generates a return value based on the specified return type and argValues.