Skip to content

Commit

Permalink
Merge pull request #14 from ppittle/multiple-creators-per-session
Browse files Browse the repository at this point in the history
added HttpWebRequestWrapperDelegateCreator
  • Loading branch information
ppittle authored Feb 20, 2018
2 parents 1d18010 + ee76511 commit 08944ac
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 0 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,25 @@ using(new HttpWebRequestWrapperSession(new CustomWrapperCreator()))
}
```

### Multiple WebRequestCreate

Have an advanced scenario where you need to use multiple `IWebRequestCreate` objects? You can use the `HttpWebRequestWrapperDelegateCreator` to decide just-in-time which `IWebRequestCreate` to use for a specific Uri:

```csharp
var creatorSelector = new Func<Uri, IWebRequestCreate>(url =>
url.Contains("api1")
? api1InterceptorCreator
: commonInterceptorCreator);

using (new HttpWebRequestWrapperSession(new HttpWebRequestWrapperDelegateCreator(creatorSelector)))
{
// handled by api1Interceptor
WebRequest.Create("http://3rdParty.com/api1/request");
// handled by commonInterceptor
WebRequest.Create("http://someother.site");
}
```

## Secret Sauce

**HttpWebRequestWrapper** works by inheriting from `HttpWebRequest`. This doesn't seem revolutionary, except these are the `HttpWebRequest` constructors:
Expand Down
69 changes: 69 additions & 0 deletions src/HttpWebRequestWrapper.Tests/DelegateCreatorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System;
using System.Net;
using Moq;
using Should;
using Xunit;

namespace HttpWebRequestWrapper.Tests
{
/// <summary>
/// Tests for <see cref="HttpWebRequestWrapperDelegateCreator"/>
/// </summary>
public class DelegateCreatorTests
{
[Fact]
public void CanUseMultipleWebRequestCreators()
{
// ARRANGE
var url1 = new Uri("http://fakesite.fake/1");
var url2 = new Uri("http://fakesite.fake/2");

var mockRequest1 = new Mock<WebRequest>();
var mockRequest2 = new Mock<WebRequest>();

var mockRequestCreator1 = new Mock<IWebRequestCreate>();
mockRequestCreator1
.Setup(x => x.Create(It.IsAny<Uri>()))
.Returns(mockRequest1.Object);

var mockRequestCreator2 = new Mock<IWebRequestCreate>();
mockRequestCreator2
.Setup(x => x.Create(It.IsAny<Uri>()))
.Returns(mockRequest2.Object);

var creatorSelector = new Func<Uri, IWebRequestCreate>(url =>
url == url1
? mockRequestCreator1.Object
: mockRequestCreator2.Object);

var delegateCreator = new HttpWebRequestWrapperDelegateCreator(creatorSelector);

WebRequest request1, request2;

// ACT
using (new HttpWebRequestWrapperSession(delegateCreator))
{
request1 = WebRequest.Create(url1);
request2 = WebRequest.Create(url2);
}

// ASSERT
request1.ShouldEqual(mockRequest1.Object);
request2.ShouldEqual(mockRequest2.Object);

mockRequestCreator1.Verify(x =>
x.Create(It.Is<Uri>(v => v == url1)),
Times.Once);
mockRequestCreator1.Verify(x =>
x.Create(It.Is<Uri>(v => v == url2)),
Times.Never);

mockRequestCreator2.Verify(x =>
x.Create(It.Is<Uri>(v => v == url1)),
Times.Never);
mockRequestCreator2.Verify(x =>
x.Create(It.Is<Uri>(v => v == url2)),
Times.Once);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="DelegateCreatorTests.cs" />
<Compile Include="InterceptorTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Extensions.cs" />
Expand Down
1 change: 1 addition & 0 deletions src/HttpWebRequestWrapper/HttpWebRequestWrapper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<ItemGroup>
<Compile Include="Extensions\RecordedRequestExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="HttpWebRequestWrapperDelegateCreator.cs" />
<Compile Include="HttpWebRequestWrapperInterceptor.cs" />
<Compile Include="HttpWebRequestWrapperInterceptorCreator.cs" />
<Compile Include="HttpWebRequestWrapperRecorder.cs" />
Expand Down
52 changes: 52 additions & 0 deletions src/HttpWebRequestWrapper/HttpWebRequestWrapperDelegateCreator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Net;

namespace HttpWebRequestWrapper
{
/// <summary>
/// Helper component that supports just-in-time selection of a
/// <see cref="IWebRequestCreate"/> based on the requested <see cref="Uri"/>.
/// <para />
/// This is only anticipated to be useful when writing BDD style
/// tests that cover a large application surface area - where the system
/// might be making calls to two different api endpoints and it is helpful to
/// have requests be routed to different <see cref="IWebRequestCreate"/>s
/// (ie <see cref="HttpWebRequestWrapperInterceptorCreator"/>) based on url.
/// <para />
/// For example, requests to http://api1/ could go to one Interceptor with a specific
/// <see cref="RecordingSession"/> and playback behavior and requests to http://api2/
/// could go to a different Interceptor with its own <see cref="RecordingSession"/>
/// and different playback behavior.
/// </summary>
public class HttpWebRequestWrapperDelegateCreator : IWebRequestCreate
{
private readonly Func<Uri, IWebRequestCreate> _creatorSelectorFunc;

/// <summary>
/// Helper component that supports just-in-time selection of a
/// <see cref="IWebRequestCreate"/> based on the requested <see cref="Uri"/>
/// via <paramref name="creatorSelector"/>.
/// <para />
/// This is only anticipated to be useful when writing BDD style
/// tests that cover a large application surface area - where the system
/// might be making calls to two different api endpoints and it is helpful to
/// have requests be routed to different <see cref="IWebRequestCreate"/>s
/// (ie <see cref="HttpWebRequestWrapperInterceptorCreator"/>) based on url.
/// <para />
/// For example, requests to http://api1/ could go to one Interceptor with a specific
/// <see cref="RecordingSession"/> and playback behavior and requests to http://api2/
/// could go to a different Interceptor with its own <see cref="RecordingSession"/>
/// and different playback behavior.
/// </summary>
public HttpWebRequestWrapperDelegateCreator(Func<Uri, IWebRequestCreate> creatorSelector)
{
_creatorSelectorFunc = creatorSelector;
}

/// <inheritdoc />
public WebRequest Create(Uri uri)
{
return _creatorSelectorFunc(uri).Create(uri);
}
}
}

0 comments on commit 08944ac

Please sign in to comment.