net.sf.surrogate.core
Class SurrogateManager

java.lang.Object
  |
  +--net.sf.surrogate.core.SurrogateManager

public class SurrogateManager
extends java.lang.Object

The link between Mock/ Unit Test objects and AspectJ code.

The SurrogateManager is the common controller for Junit tests manipulating MockObjects and mock methods.

Test Case View

The SurrogateManager provides utility methods for test cases to control which Mock objects should be active for a particular test case run. These methods are normally:
    getInstance()
    reset()
    addMock(Object)
    addMockMethod(MockMethod)
    removeMock(Object)
    removeMockMethod(MockMethod)
 

Aspect View

Every time an aspect detects a "mock poincut", it will ask the SurrogateManager if a mock object has been registered for the corresponding joinpoint. If so, the mock executes instead of the "real" method. Otherwise, the real object is allowed to execute. The methods used by the aspects are normally:
   getInstance()
   getMockExecutor(JoinPoint)
 

Test Case responsibility

A test case should normally always call the reset()method before starting to use the SurrogateManager to avoid independence from other testcases which might have been run earlier from within the same VM.

Debugging

If the System property "surrogate.debug" is set to "true", e.g. with the java -Dsurrogate.debug=true option, the SurrogateManager will report every time it is asked to resolve a JoinPoint into a mock object or method. The information is written to System.out. Each debug line is on the following format:
   surrogate:<joinpoint id>|added|removed=<mock id>
   
   Example:
   surrogate:added=public static native long java.lang.System.currentTimeMillis()
   surrogate:added=net.sf.surrogate.example.MockFileWriter@38e059
   surrogate:call(long java.lang.System.currentTimeMillis())=public static native long java.lang.System.currentTimeMillis()
   surrogate:call(java.io.FileWriter(String))=net.sf.surrogate.example.MockFileWriter@38e059
   surrogate:call(java.io.BufferedWriter(Writer))=null
 
I.e. the unit test has added mocks for currentTimeMillis and the FileWriter. As expected, mocks were returned for the currentTimeMillis and FileWriter mockJoinPoint's but no mock was found for the BufferedWriter joinpoint (null was returned).

Author:
Per S Hustad
See Also:
SurrogateCalls, MockMethod

Inner Class Summary
static interface SurrogateManager.MockExecutor
          Defines, towards the AspectJ layer, the mock object or method to be executed.
 
Method Summary
 java.lang.Object addMock(java.lang.Object o)
          Adds a Mock object to the manager for later lookup by Aspect code.
 MockMethod addMockMethod(MockMethod m)
          Adds a mock method to the manager for later lookup by Aspect code.
protected static SurrogateManager createInstance()
          Created an instance of the manager.
static SurrogateManager getInstance()
          Gets the manager singleton
(package private)  MockMethod getMockConstructor(java.lang.reflect.Constructor c)
          Gets a registered Mock method reference for a constructor
 SurrogateManager.MockExecutor getMockExecutor(org.aspectj.lang.JoinPoint p)
          Gets the mock object or mock method for a joinpoint.
protected  MockMethod getMockMethod(org.aspectj.lang.JoinPoint p)
          Checks if an AspectJ "mock" joinpoint has an assoicated mock method registered by the manager.
(package private)  MockMethod getMockMethod(java.lang.reflect.Method m)
          Gets a registered Mock method reference for a method.
(package private)  java.lang.Object getMockObject(java.lang.Class myClassOrInterface)
          Locates and gets a Mock object for an interface or a class.
protected  java.lang.Object getReturnedClassMock(org.aspectj.lang.JoinPoint p)
          Checks if an AspectJ "mock" joinpoint has an assoicated mock object registered by the manager.
 java.lang.Object removeMock(java.lang.Object o)
          Removes a mock from the manager.
 MockMethod removeMockMethod(MockMethod m)
          Removes a mock method from the manager.
 void reset()
          Removes all Mock objects and methods from the list of active objects.
 
Methods inherited from class java.lang.Object
, clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

getInstance

public static SurrogateManager getInstance()
Gets the manager singleton
Returns:
the manager instance.
See Also:
reset()

createInstance

protected static SurrogateManager createInstance()
Created an instance of the manager. Override this method if you want to create a subclass of the manager
Returns:
a new instance of the manager

reset

public void reset()
Removes all Mock objects and methods from the list of active objects. This method should be called by every TestCase method to ensure that "old" Mocks created by other testcases are not hanging around in the system ...

addMock

public java.lang.Object addMock(java.lang.Object o)
Adds a Mock object to the manager for later lookup by Aspect code.

Note that for objects to be substituted with their mock implementation, there must have been defined a pointcut intercepting the method call or method execution. Otherwise, the mock object will never be substituted, even if it has been registered. See SurrogateCalls for pointcut definition details.

Surrogate uses the java.lang.Class.isAssignableFrom to see whether the registered mock can subsitute a "real" object. It does this by looking up the declared return type signature of the method or the class signature of the constructor call.

Example usage:

 
       SurrogateManager mm = SurrogateManager.getInstance();
       mm.reset();
       MockCustomerService mock = new MockCustomerService();
       mm.addMock(mock);
       mock.setGetCustomerReturnValue("MockCustomer");
       ...
  
 
Parameters:
o - the Mock object to add. Must be non-null.
Returns:
the Mock object given as argument
See Also:
addMockMethod(MockMethod), removeMock(Object), SurrogateCalls

addMockMethod

public MockMethod addMockMethod(MockMethod m)
Adds a mock method to the manager for later lookup by Aspect code.

Note that for objects to be substituted with their mock implementation, there must have been defined a pointcut intercepting the method call or method execution. Otherwise, the mock object will never be substituted, even if it has been registered. See SurrogateCalls for pointcut definition details.

Example usage:

       SurrogateManager mm = SurrogateManager.getInstance();
       mm.reset();
       MockMethod mockTime = 
            mm.addMockMethod(new MockMethod(System.class,"currentTimeMillis"));
       mockTime.addReturnValue(1000L);
       mockTime.addReturnValue(2000L);
       mockTime.setExpectedCalls(2);
       ... Call object using System.currentTimeMillis
       mockTime.verify(); 
       ...
 
Parameters:
m - the Mock object to add. Must be non-null.
Returns:
the MockMethod as given on input
See Also:
addMock(Object), removeMockMethod(MockMethod)

removeMock

public java.lang.Object removeMock(java.lang.Object o)
Removes a mock from the manager. The object will hence no longer be returned instead of a "real" object when the corresponding aspect advice executes
Parameters:
o - the object to remove.
Returns:
the removed object or null if the object was not found
See Also:
addMock(Object)

removeMockMethod

public MockMethod removeMockMethod(MockMethod m)
Removes a mock method from the manager. The method will hence no longer execute instead of the "real" method when the corresponding aspect advice executes.
Parameters:
o - the object to remove.
Returns:
the removed method or null if the mock method was not found.
See Also:
addMockMethod(MockMethod)

getMockObject

java.lang.Object getMockObject(java.lang.Class myClassOrInterface)
Locates and gets a Mock object for an interface or a class. This method looks for a Mock object implementing the interface or the class assignable from myClassOrInterface by searching in the list of Mock objects for the first object which myClassOrInterface is assignable from
Parameters:
myClassOrInterface - the interface/class to find a mock object for
Returns:
the Mock object for the interface/class or null if no such mock object has been registered via the addMock method.
See Also:
addMock(Object), Class.isAssignableFrom(java.lang.Class)

getMockMethod

MockMethod getMockMethod(java.lang.reflect.Method m)
Gets a registered Mock method reference for a method. This method should normally only be called from the aspect code.
Parameters:
m - the Method to check
Returns:
the registered Mock method reference or null if no such reference exists for the method
See Also:
addMockMethod(MockMethod)

getMockConstructor

MockMethod getMockConstructor(java.lang.reflect.Constructor c)
Gets a registered Mock method reference for a constructor
Parameters:
c - the constructor to check
Returns:
the registered Mock method reference or null if no such reference exists for the method
See Also:
addMockMethod(MockMethod)

getReturnedClassMock

protected java.lang.Object getReturnedClassMock(org.aspectj.lang.JoinPoint p)
                                         throws java.lang.IllegalArgumentException
Checks if an AspectJ "mock" joinpoint has an assoicated mock object registered by the manager.
Parameters:
p - the join point
Returns:
the corresponding mock object or null if no match is found

getMockMethod

protected MockMethod getMockMethod(org.aspectj.lang.JoinPoint p)
                            throws java.lang.IllegalArgumentException,
                                   java.lang.NoSuchMethodException
Checks if an AspectJ "mock" joinpoint has an assoicated mock method registered by the manager.
Parameters:
p - the join point
Returns:
the corresponding mock method or null if no match is found
Throws:
java.lang.IllegalArgumentException - if the joinpoint signature is not a "method" or "constructor" signature

getMockExecutor

public SurrogateManager.MockExecutor getMockExecutor(org.aspectj.lang.JoinPoint p)
                                              throws java.lang.IllegalArgumentException,
                                                     java.lang.NoSuchMethodException
Gets the mock object or mock method for a joinpoint. This method should normally only be called from the corresponding SurrogateCalls advice but can also be called from other advices which might want to check if a mock matches the joinpoint.

The rules are as follows

The advices should, if receiving a non-null MockExecutor return value, call the MockExecutor.execute with the same JoinPoint as used as arguments to getMockExecutor. If the returned MockExecutor is null, the advice should return a sensible value, e.g. with return proceed();
Parameters:
p - the thisJoinPoint on the advice executing
Returns:
the corresponding mock executor or null if no match has been found with a registered mock object or mock method
Throws:
java.lang.IllegalArgumentException - if the joinpoint signature is not a "constructor" or "method" signature.
java.lang.NoSuchMethodException - if the joinpoint is inconsistent. This should normally be considered as a bug.
See Also:
SurrogateCalls, addMock(Object), addMockMethod(MockMethod)


Copyright © 2005 . All Rights Reserved.