com.mockrunner.connector.MappedRecordInteraction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mockrunner-jca Show documentation
Show all versions of mockrunner-jca Show documentation
Mock classes for Java Connector Architecture
package com.mockrunner.connector; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.resource.ResourceException; import javax.resource.cci.InteractionSpec; import javax.resource.cci.MappedRecord; import javax.resource.cci.Record; import com.mockrunner.base.NestedApplicationException; import com.mockrunner.mock.connector.cci.MockMappedRecord; /** * This interaction implementor works with mapped records. It takes a
class * @throws IllegalArgumentException if theMap
for * the request and aMap
or aRecord
instance for the response. * If the requestMap
isnull
, which is the default, * the implementor accepts any request and returns the specified result. If a request *Map
is specified, this implementor accepts only requests that contain the same * data as the specified expected requestMap
. The underlying maps are compared * as described in theMap.equals
method. * If a request is accepted, this implementor replies with the specified * response. You can use the various constructors andset
methods * to configure the expected request and the response.
* Please check out the documentation of the various methods for details. */ public class MappedRecordInteraction implements InteractionImplementor { private boolean enabled; private Map expectedRequest; private Map responseData; private Class responseClass; private Record responseRecord; /** * Sets the expected request and the response tonull
, * i.e. an empty response is returned for every request. */ public MappedRecordInteraction() { this(null, null, MockMappedRecord.class); } /** * Sets the expected request tonull
and prepares * the specified responseMap
. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the default {@link com.mockrunner.mock.connector.cci.MockMappedRecord}. * It is allowed to passnull
for the responseMap
* which is equivalent to an empty response. * The specified response is returned for every request. * @param responseMap the responseMap
*/ public MappedRecordInteraction(Map responseMap) { this(null, responseMap, MockMappedRecord.class); } /** * Sets the specified expected requestMap
and prepares * the specified responseMap
. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the default {@link com.mockrunner.mock.connector.cci.MockMappedRecord}. * It is allowed to passnull
for the request and responseMap
* which is equivalent to an empty expected request (i.e. every request is accepted) * or to an empty response respectively. * The specified response is returned, if the actual request matches the specified expected * request. * @param expectedRequest the expected requestMap
* @param responseMap the responseMap
*/ public MappedRecordInteraction(Map expectedRequest, Map responseMap) { this(expectedRequest, responseMap, MockMappedRecord.class); } /** * Sets the expected request tonull
and prepares * the specified responseMap
. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the specifiedresponseClass
. The specified *responseClass
must implementMappedRecord
, * otherwise anIllegalArgumentException
will be thrown. * It is allowed to passnull
for the responseMap
* which is equivalent to an empty response. * The specified response is returned for every request. * @param responseMap the responseMap
RecordresponseClass
* is not valid */ public MappedRecordInteraction(Map responseMap, Class responseClass) { this(null, responseMap, responseClass); } /** * Sets the specified expected requestMap
and prepares * the specified responseMap
. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the specifiedresponseClass
. The specified *responseClass
must implementMappedRecord
, * otherwise anIllegalArgumentException
will be thrown. * It is allowed to passnull
for the request and responseMap
* which is equivalent to an empty expected request (i.e. every request is accepted) * or to an empty response respectively. * The specified response is returned, if the actual request matches the specified expected * request. * @param expectedRequest the expected requestMap
* @param responseMap the responseMap
Record class * @throws IllegalArgumentException if theresponseClass
* is not valid */ public MappedRecordInteraction(Map expectedRequest, Map responseMap, Class responseClass) { setExpectedRequest(expectedRequest); setResponse(responseMap, responseClass); this.enabled = true; } /** * Sets the specified expected requestMap
and the response *Record
for the {@link #execute(InteractionSpec, Record)} * method. The responseRecord
is ignored for * {@link #execute(InteractionSpec,Record,Record)} but takes precedence * over the specified responseMap
for {@link #execute(InteractionSpec, Record)}. * It is allowed to passnull
for the request and responseRecord
* which is equivalent to an empty expected request (i.e. every request is accepted) * or to no specified responseRecord
, i.e. the specified response *Map
is taken. * The specified response is returned, if the actual request matches the specified expected * request. * @param expectedRequest the expected requestMap
* @param responseRecord the responseRecord
*/ public MappedRecordInteraction(Map expectedRequest, Record responseRecord) { setExpectedRequest(expectedRequest); setResponse(responseRecord); this.enabled = true; } /** * Sets the expected request tonull
and prepares the response *Record
for the {@link #execute(InteractionSpec, Record)} * method. The responseRecord
is ignored for * {@link #execute(InteractionSpec,Record,Record)} but takes precedence * over the specified responseMap
for {@link #execute(InteractionSpec, Record)}. * It is allowed to passnull
for the responseRecord
* which is equivalent to no specified responseRecord
, i.e. the specified response *Map
is taken. * The specified response is returned for every request. * @param responseRecord the responseRecord
*/ public MappedRecordInteraction(Record responseRecord) { this(null, responseRecord); } /** * Enables this implementor. */ public void enable() { this.enabled = true; } /** * Disables this implementor. {@link #canHandle(InteractionSpec, Record, Record)} * always returnsfalse
, if this implementor is disabled. */ public void disable() { this.enabled = false; } /** * Sets the specified expected requestMap
. The response is returned, * if the actual request matches the specified expected requestMap
* according toMap.equals
. * It is allowed to passnull
for the requestMap
* which is equivalent to an empty expected request (i.e. every request * is accepted). * @param expectedRequest the expected requestMap
*/ public void setExpectedRequest(Map expectedRequest) { if(null == expectedRequest) { this.expectedRequest = null; } else { this.expectedRequest = new HashMap(expectedRequest); } } /** * Prepares the specified responseMap
. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the default {@link com.mockrunner.mock.connector.cci.MockMappedRecord}. * It is allowed to passnull
for the responseMap
* which is equivalent to an empty response. * @param responseMap the responseMap
Map. The response class for the * {@link #execute(InteractionSpec,Record)} method is set * to the specifiedresponseClass
. The specified *responseClass
must implementMappedRecord
, * otherwise anIllegalArgumentException
will be thrown. * It is allowed to passnull
for the responseMap
* which is equivalent to an empty response. * @param responseMap the responseMap
* @param responseClass the responseRecord
class * @throws IllegalArgumentException if theresponseClass
* is not valid */ public void setResponse(Map responseMap, Class responseClass) { if(!isResponseClassAcceptable(responseClass)) { throw new IllegalArgumentException("responseClass must implement " + MappedRecord.class.getName()); } if(null == responseMap) { this.responseData = null; } else { this.responseData = new HashMap(responseMap); } this.responseClass = responseClass; } /** * Prepares the responseRecord
for the * {@link #execute(InteractionSpec, Record)} method. The response *Record
is ignored for {@link #execute(InteractionSpec,Record,Record)} * but takes precedence over the specified responseMap
for * {@link #execute(InteractionSpec, Record)}. * It is allowed to passnull
for the responseRecord
* which is equivalent to no specified responseRecord
, i.e. the specified response *Map
is taken. * @param responseRecord the responseRecord
*/ public void setResponse(Record responseRecord) { this.responseRecord = responseRecord; } /** * Returnstrue
if this implementor is enabled and will handle the request. * This method returnstrue
if the following prerequisites are fulfilled:
* It is enabled.
* The responseRecord
must implementMappedRecord
* or it must benull
(which is the case, if the actual request * targets the {@link #execute(InteractionSpec,Record)} method instead of * {@link #execute(InteractionSpec,Record,Record)}).
* The expected request must benull
(use the various *setExpectedRequest
methods) or the actual requestRecord
* must implementMappedRecord
and must contain the same data as * the specified expected requestMap
according toMap.equals
.
* Otherwise,false
is returned. * @param interactionSpec theInteractionSpec
for the actual call * @param actualRequest the request for the actual call * @param actualResponse the response for the actual call, may benull
* @returntrue
if this implementor will handle the request and * will return the specified response,false
otherwise */ public boolean canHandle(InteractionSpec interactionSpec, Record actualRequest, Record actualResponse) { if(!enabled) return false; if(!isResponseAcceptable(actualResponse)) return false; return doesRequestMatch(actualRequest); } private boolean doesRequestMatch(Record request) { if(null == expectedRequest) return true; if(null == request) return false; if(request instanceof MappedRecord) { try { MappedRecord mappedRequest = (MappedRecord)request; if(mappedRequest.size() != expectedRequest.size()) return false; Iterator keys = mappedRequest.keySet().iterator(); while(keys.hasNext()) { Object nextKey = keys.next(); Object actualValue = mappedRequest.get(nextKey); Object expectedValue = expectedRequest.get(nextKey); if(!areObjectsEquals(actualValue, expectedValue)) { return false; } } return true; } catch(Exception exc) { throw new NestedApplicationException(exc); } } return false; } private boolean areObjectsEquals(Object object1, Object object2) { if(null == object1 && null == object2) return true; if(null == object1) return false; return object1.equals(object2); } private boolean isResponseAcceptable(Record response) { return (null == response) || (response instanceof MappedRecord); } private boolean isResponseClassAcceptable(Class responseClass) { return (null == responseClass) || (MappedRecord.class.isAssignableFrom(responseClass)); } /** * First version of theexecute
methods.
* This method returnsnull
, if the request does not match * according to the contract of {@link #canHandle}. This never happens under * normal conditions since the {@link InteractionHandler} does not call *execute
, if {@link #canHandle} returnsfalse
. *
* Otherwise, this method returns the specified response. If a response *Record
object is specified (use {@link #setResponse(Record)}), * it always takes precedence, i.e. the responseMap
will be ignored. * If noRecord
object is specified, aRecord
object * is created and filled with the specified responseMap
data. Use the *setResponse
methods that take aMap
* to prepare the responseMap
. The createdRecord
is of the the * specified type (thesetResponse
method that takes a second *Class
parameter allows for specifying a type). If no type * is specified, a {@link com.mockrunner.mock.connector.cci.MockMappedRecord} * is created. If no responseMap
is specified at all, an empty * {@link com.mockrunner.mock.connector.cci.MockMappedRecord} * will be returned. * @param interactionSpec the interaction spec * @param actualRequest the actual request * @return the response according to the current request */ public Record execute(InteractionSpec interactionSpec, Record actualRequest) throws ResourceException { if(!canHandle(interactionSpec, actualRequest, null)) return null; if(null != responseRecord) return responseRecord; MappedRecord response = null; try { if(null == responseClass) { response = new MockMappedRecord(); } else { response = (MappedRecord)responseClass.newInstance(); } if(null != responseData) { response.putAll(responseData); } } catch(Exception exc) { ResourceException resExc = new ResourceException("execute() failed"); resExc.setLinkedException(exc); throw resExc; } return (Record)response; } /** * Second version of theexecute
methods.
* This method returnsfalse
, if the request does not match * according to the contract of {@link #canHandle}. This never happens under * normal conditions since the {@link InteractionHandler} does not call *execute
, if {@link #canHandle} returnsfalse
. *
* Otherwise, this method fills the responseRecord
with the * specified responseMap
data. Use thesetResponse
methods that * take aMap
to prepare the responseMap
. * The responseRecord
must implementMappedRecord
* (it does, otherwise the request would have been rejected by * {@link #canHandle}). If no responseMap
is specified at all, * the responseRecord
is not touched buttrue
* is returned anyway * @param interactionSpec the interaction spec * @param actualRequest the actual request * @param actualResponse the actual response * @returntrue
under normal conditions */ public boolean execute(InteractionSpec interactionSpec, Record actualRequest, Record actualResponse) throws ResourceException { if(!canHandle(interactionSpec, actualRequest, actualResponse)) return false; try { if(null != responseData && null != actualResponse) { ((MappedRecord)actualResponse).clear(); ((MappedRecord)actualResponse).putAll(responseData); } } catch(Exception exc) { ResourceException resExc = new ResourceException("execute() failed"); resExc.setLinkedException(exc); throw resExc; } return true; } }