Mock HTTP layer to do complex tasks like uploading photo to Flickr

In this post, I will show how you can use Typemock to fake out complex HTTP POST like uploading photo in Flickr server. The example which will be shown here, gives a pretty much generic idea of faking out HTTP calls and gain access to the response stream for comparing result with original content.I have used, N-Unit along with Typemock which run thorough TMockRunner.exe to perform the mock test.

To get started, let's see what is really cooking in PhotoRepository.Upload in LINQ.Flickr which we are going to mock.

image

To focus strictly on mocking,  I have removed non-mockable parts and blocked out sections to be mocked. These include the following

1. Mock calls to Authenticate.

2. Get a mocked signature.

3. Mock the HttpRequest object

4. Get reference of the Stream so that Stream.Write  writes to our desired media rather to the original request stream.

5. Create a Fake WebResponse object and marry it with Request.GetResponse

6. Get reference of the response stream  that will be filled with data from local resource.

Staring off every mock should have a MockManager.init(). we can further check if it is initialized or not by MockManager.Isinitialized.I have moved the common mock statements to a separate class for LINQ.Flickr which I call FakeFlickrReposity. It takes in the type of repository and the returned object and it can be constructed by a simple using block as it implements IDisposable.

using (FakeFlickrRepository<PhotoRepository, Photo> photoAddMock = 
new FakeFlickrRepository<PhotoRepository, Photo>()) 
{ 
   ... 
   ... 
}

Inside it creates a Mock in its constructor of type PhotoRepository, the method of which(Also, its base) to be mocked.

public FakeFlickrRepository()
{
    _mockRepository = MockManager.Mock<T>(Constructor.NotMocked);
}

The Constructor.NotMocked, means that the initialization codes for PhotoRepository wont be skipped. In this case creating the interface mapping to endpoint, getting keys, paths, etc.Now, going into the test class of LINQ.Flickr for uploading photo, I have first created the Photo object that has stream reference of a file from local resource.

//[Following block used in the full codeview at the bottom]
Stream photoRes = 
GetResourceStream("Linq.Flickr.Test.blank.gif"); 
Photo photo = 
new Photo { Title = "Flickr logo", FileName = "Test.Mock",
File = photoRes, ViewMode = ViewMode.Public };

Next, called the following

photoAddMock.MockAuthenticateCall(true, Permission.Delete);
photoAddMock.MockSignatureCall();

Inside of MockAuthenticateCalls looks like

_mockRepository.
ExpectAndReturn("Authenticate", authToken)
.Args(validate, permission.ToString());

And inside of MockSignatureCall

_mockRepository.ExpectAndReturn("GetSignature", signature);

ExpectAndReturn , as it looks like, traps a method call and returns the result right away rather going to the original flow.

 

photoAddMock.FakeHttpRequestObject(fileStream);

The above line is for faking HTTPWebRequest and get a stream reference out of it. Stepping in which we can see

_httpRequestMock = MockManager.Mock(typeof(HttpWebRequest)); A 
_httpRequestMock.ExpectSet("ContentType"); B
_httpRequestMock.ExpectAndReturn("GetRequestStream", stream); C

A => Creates a mock of Type HttpWebRequest, B=> Sets an expectation of ContentType set, setting ContentType with mocked request will give a null reference as it depends on internal dictionary to do processing. C=> Sets an expection of GetRequestStream  and returns the reference to the stream provided from outside.

photoAddMock.FakeWebResponse_GetResponse();

 

This will create a MockObject of type WebResponse class and will return a dummy instance of it when HttpRequest.GetResponse will be invoked.

_webResponseMock = MockManager.MockObject<WebResponse>();
_httpRequestMock.ExpectAndReturn("GetResponse", _webResponseMock.Object);

_httpRequestMock  is the private Mock variable that we created earlier. We also need to fill up the Response stream with proper Flickr response to be parsed by the LINQ.Flcikr system properly , in case of successful upload. To archive that, we need to marry our local resource stream to the WebResponse.GetResponStream

_webResponseMock.
ExpectAndReturn("GetResponseStream", GetResourceStream(resource));
_webResponseMock.ExpectCall("Close");

Finally, we need to make sure that response stream is closed properly. This is pretty much all which is to be mocked, the rest part of the code is to read the stream where the uploaded content is saved (pointed by us) and compare it with original photo binary.

The part of the code is pasted here for more info of what I just said.

image

This whole implementation can be found at LINQ.Flickr.Test under PhotoMockTest :: DoPhotoUploadAndDeleteTest, which can be downloaded from www.codeplex.com/linqflickr. Have a nice day!!

kick it on DotNetKicks.com

No Comments