ashevin / ANSRequestMocker

Simple HTTP(S) request mocking in Objective-C

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ANSRequestMocker

Simple HTTP(S) request mocking in Objective-C

This class allows for intercepting HTTP and HTTPS requests sent through NSURLConnection and NSURLSesssion. The client app sets up filters which limit the requests which are intercepted. Filtered requests can be responded to as the client wishes. The goal is to allow for testing server APIs that may not be ready yet, or to test specific conditions, such as errors, that may not be easy to trigger on demand. The facility also has obvious uses in unit testing.

ANSRequestFilter

Filters are instances of ANSRequestFilter. There are several init methods available, which provide differing control over specific options. Filters are matched in the order they are registered, so place more specific filters before more general filters.

The two main init methods are:

  • (instancetype)initWithHost:(NSString *)host path:(NSString *)path httpMethod:(NSString *)httpMethod responseDictionary:(NSDictionary *)responseDictionary dataObject:(id)dataObject;

  • (instancetype)initWithHost:(NSString *)host path:(NSString *)path httpMethod:(NSString *)httpMethod responseDictionary:(NSDictionary *)responseDictionary dataBlock:(ANSRequestFilterDataBlock)dataBlock;

Parameters:

host : the host name which will appear in the request.  Do not include the protocol
		scheme.
path : the path portion of the URL.  Leading /'s are ignored when matching.  Wildcards
		 are permitted, detailed below.
httMethod : the http method of the request.  Filtering is specific to the method,
			so the same host+path combination with a different method will not
			be intercepted.  The common methods are GET and POST.
responseDictionary : this dictionary is used to specify parameters to be set in the
						response, detailed below.
dataObject : When the response is fixed, it can specified using this parameter.  The
				object should be of type NSData.  If an NSDictionary is supplied, it
				will be serialized to JSON on your behalf.
dataBlock : A block which will be called when a request is intercepted.  It is 
			provided the filter and the request as parameters.  The block must return
			an NSData object.

Wildcards:

The path parameter of the filter may include wildcards.  The supported wildcards are
asterisk (*) and variables.

The * can be used to wildcard a single path component, or when the only component,
will match any URL.  Multiple wildcards may be included in the same path
specification.

Variables are specified as a path section which is wrapped in braces ({}).  The
text between the braces are treated as the variable name.  Variables are made
available to the dataBlock through the filter parameter's variables property.  This
property is a dictionary mapping of variable name to the value found in the request's
path.

responseDictionary:

The responseDictionary allows setting the following attributes of a request, by
including the appropriate key.  Any keys not included are given sensible defaults.

	status code : kANSFilterResponseStatusCode
					Specify as NSString or NSNumber, defaults to 200.
	HTTP version : kANSFilterResponseHTTPVersion
					Specify as NSString, defaults to "HTTP/1.1"
	content type : kANSFilterResponseHeaderContentType
					Specifies as NSString, there is no default, with the exception
					that passing an NSDictionary to the dataObject parameter will
					default to "application/json"
	header fields : kANSFilterResponseHeaderFields
					Custom header fields may be specified to be returned.  The value
					is a dictionary of header names and their values.

Examples:

Wildcards:

	filter:		*
	matches:	<anything>
	
	filter:		/some/path/*
	matches:	/some/path/resource
	! matches:	/some/path/to/resource
	
	filter:		/*/path
	matches:	/some/path
	! matches: 	/some/path/to/resouce
	
	filter:		/*/path/*
	matches:	/some/path/resouce
	! matches:	/some/path
	
	
Variables:

	filter:		/user/{userId}
	request:	/user/12345
	variable:	userId = 12345
	
	filter:		/user/{userId}/delete
	request:	/user/12345
	variable:	userId = 12345
			
	filter:		/user/{userId}/{operation}
	request:	/user/12345/delete
	variable:	userId = 12345
	variable:	operation = delete
	
	
Filter initialization:

	This filter will return a hard-coded avatar image for the given userId.
	
	[[ANSRequestFilter alloc] initWithHost:@"example.com"
                    path:@"/user/12345/avatar"
              httpMethod:@"GET"
      responseDictionary:@{ kANSFilterResponseHeaderContentType : @"image/png" }
              dataObject:UIImagePNGRepresentation([UIImage imageNamed:@"avatar.png")]


	This filter will return information for a newly-registering user.  The body is
	assumed to be JSON.
	
	[[ANSRequestFilter alloc] initWithHost:@"example.com"
                    path:@"/user/register"
              httpMethod:@"POST"
      responseDictionary:@{ kANSFilterResponseHeaderContentType : @"application/json" }
               dataBlock:^id(ANSRequestFilter *filter, NSURLRequest *request) {
					NSDictionary *b = [NSJSONSerialization JSONObjectWithData:request.HTTPBody
                                                      			      options:0
																	    error:NULL];
																	    
					NSUInteger userId = [self generateUserId];
					
					NSDictionary *d = @{
										@"userId" : userId,
										@"firstName" : b[@"firstName"],
										@"lastName" : b[@"lastName"],
										@"avatar" : [NSString stringWithFormat:@"https://example.com/user/%llu/avatar", userId],
									   }
									   
					return [NSJSONSerialization dataWithJSONObject:d options:0 error:NULL];
				}

Usage:

Filtering is done via a concrete subclass of NSURLProtool.  The fist step is to
register ANSRequestMocker with the URL loading subsytem.  Registered classes are
each given a chance to handle a request; the first class to respond affirmatively
will be used.  Classes are checked in the reverse order of registration, so it's
important to register ANSRequestMocker after any other implementations.

	Registration: [ANSRequestMocker registerClass:[ANSRequestMocker class]];
	
The second step is to register filters.

	Filter registration: [ANSRequestMocker registerFilters:@[ filter1, filter2 ]];

About

Simple HTTP(S) request mocking in Objective-C

License:MIT License


Languages

Language:Objective-C 100.0%