0

I apologize if this a duplicate question (I didn't find anything like that). I'm trying to build an OpenId Authentication service and unit test it, currently I have the following setup:

public class OpenIdAuthenticationService : IAuthenticationService
{
    private IConfigurationService   _configService;
    private OpenIdRelyingParty      _openIdRelyingParty;

    public OpenIdAuthenticationService(IConfigurationService configService)
    {
        _configService      = configService;
        _openIdRelyingParty = new OpenIdRelyingParty();            
    }
}

Apparently OpenIdRelyingParty requires access to HttpContext, is there a way to mock OpenIdRelyingParty and inject it the service ? Or maybe mock HttpContext and provide it to OpenIdRelyingParty somehow ?

Dimitar Dimitrov
  • 14,868
  • 8
  • 51
  • 79

3 Answers3

1

I would, since you are already doing it, inject OpenIdRelyingParty into your constructor as you are doing with your configuration service.

Barring that, you could mock the HttpContext in your unit test. HttpContext.Current has a setter, so set it to a mock/stub HttpContextBase. Here's an example using NSubstitute with NUnit:

[TearDown]
public void CleanUp()
{
    HttpContext.Current = null;
}

[Test]
public void FakeHttpContext()
{
    var context = Substitute.For<HttpContextBase>();
    var request = Substitute.For<HttpRequestBase>();
    context.Request.Returns(request);
    //Do any more arragement that you need.

    //Act

    //Assert
}

This to me would be a bit of a code smell though. It's testing dependencies of dependencies (or however far down that rabbit hole goes). It's useful though when refactoring isn't an option.

vcsjones
  • 138,677
  • 31
  • 291
  • 286
  • Thanks I can take the OpenIdRelyingParty out and inject it through the constructor, however how would I initialize it in my unit test ? It requires HttpContext and yet there is no way to provide it ? – Dimitar Dimitrov May 23 '12 at 15:11
  • 1
    @2Dim1 Inject an interface of it through the constructor, then mock the interface. That way no "real" implementation is used, and it will never hit the HttpContext. – vcsjones May 23 '12 at 15:12
  • I appreciate your help. Well to be honest I've tried that, however it appears that OpenIdRelyingParty is not the implementation of IOpenIdRelyingParty in DotNetOpenAuth ? Unless I'm missing something ? – Dimitar Dimitrov May 23 '12 at 15:16
1

To mock HttpContext for OpenIdRelyingParty you should modify the code of that class. Even you would waste some time mocking it due that it is a sealed class (but is not impossible you can use MOCKWCF).

I think that is better make a wrapper or adapter for OpenIdRelyingParty. like:

public class OpenIdRelyingPartyWrapped
{
    private OpenIdRelyingParty openIdRelyingPartyTarget;
    ....
    public virtual IAuthenticationRequest CreateRequest(string text)
    {
        return this.openIdRelyingPartyTarget.CreateRequest(text);
    }
    ...
} 

Then you will able to mock it as you want.

Marco Medrano
  • 2,530
  • 1
  • 21
  • 35
  • Thank you, I like this approach, but in this case, how would I initialize OpenIdRelyingParty ? Should I initialize it out of the wrapper and inject it ? Or should I check if it's null and define a default value ? Or I'm missing something ? – Dimitar Dimitrov May 24 '12 at 06:26
  • 1
    That depends on the strategy to make instances if you are using **IOC** you should keep that, then the injection would be by constructor or by a property. If you are not using IOC you can just make the instance in the constructor of **OpenIdRelyingPartyWrapped**. For or your unit tests you should make a mock class that inherit from **OpenIdRelyingPartyWrapped** and override the methods that you want to mock. – Marco Medrano May 24 '12 at 14:58
1

OpenIdRelyingParty can be used in unit tests by using the method overloads that accept an HttpRequestBase, which is totally mockable. Only the methods that don't take that as a parameter require an HttpContext.Current.

Andrew Arnott
  • 80,040
  • 26
  • 132
  • 171