0

I've got a class inside a class library that should be used by Windows application nor Web application.

it's defined as

 public class CredentialProviderPipelineStep
{
    internal static string GetDomainFullName(string friendlyName)
    {
        var context = new DirectoryContext(DirectoryContextType.Domain, friendlyName);
        var domain = Domain.GetDomain(context);
        return domain?.Name;
    }


    public static Task<IDictionary<string, object>> Action(IConfiguration configuration)
    {

        return Task.Run<IDictionary<string, object>>(() =>
               {
                   var context = new Dictionary<string, object>
                   {
                       [Resources.DomainName] = GetDomainFullName(Environment.UserDomainName),
                       [Resources.DomainUser] = Environment.UserName
                   };

                   if (configuration.AppSettings[Resources.SSOApplicationId] == null)
                       throw new KeyNotFoundException(Resources.SSOApplicationId);

                   context[Resources.ApplicationId] =
                       Convert.ToInt32(configuration.AppSettings[Resources.SSOApplicationId]);

                   return context;
               });
    }

    internal static IDictionary<string, object> GetUserAndDomain()
    {
        //It's to check if it's a web app, so I've to ask for principal data <see href="http://stackoverflow.com/questions/3179716/how-determine-if-application-is-web-application/"></see>
        return Assembly.GetEntryAssembly() == null ? GetUserAndDomainFromWebApp() : GetUserAndDomainFromEnviorment();
    }

    private static IDictionary<string,object> GetUserAndDomainFromEnviorment()
    {

        var httpContext = System.Web.HttpContext.Current.User.Identity.Name;

        string[] splitted = httpContext.Split('\\');

        var result = new Dictionary<string, object>
        {
            [Resources.DomainName] = GetDomainFullName(Environment.UserDomainName),
            [Resources.DomainUser] = Environment.UserName
        };

        return result;
    }

    private static IDictionary<string, object> GetUserAndDomainFromWebApp()
    {
        var result = new Dictionary<string, object>
        {
            [Resources.DomainName] = GetDomainFullName(Environment.UserDomainName),
            [Resources.DomainUser] = Environment.UserName
        };

        return result;
    }

}

The canonical UnitTest (using NUnit) cover the GetUserAndDomainFromEnviorment part , but how can I write a unit test that cover the GetUserAndDomainFromWebApp method? so it has the System.Web.HttpContext.Current.User.Identity.Name filled?

Thanks

advapi
  • 3,661
  • 4
  • 38
  • 73

1 Answers1

1

I suggest removing the dependency on System.Web.HttpContext in your class library. This can be done by a simple interface that returns the Identity. Here's the interface:

public interface IdentityProvider
{
  System.Security.Principal.IIdentity GetIdentity();
}

Now, remove the static keyword on the methods you want to unit test. Create a constructor for the CredentialProviderPipelineStep class that takes the interface as a parameter:

public CredentialProviderPipelineStep
{
  IdentityProvider _identityProvider;

  public CredentialProviderPipelineStep(IdentityProvider identityProvider)
  {
    _identityProvider = identityProvider;
  }
  ...
}

Then make one implementation of the interface for the web that simply returns the Identity stored in HttpContext. The other implementation would probably return the Identity from System.Threading.Thread.CurrentPrincipal.Identity which contains information about the logged in user in Windows.

By now, you can remove the GetUserAndDomain() method that tries to find out whether you're in web context or not.

It is now up to your web application or Windows application to deliver the appropriate implementation of the interface to CredentialProviderPipelineStep.

This technique is often called Dependency Inversion which is the D in the SOLID principles.

Here's a good talk on Dependency Inversion: Inversion of Control from First Principles - Top Gear Style (and it's quite entertaining too).

Nkosi
  • 235,767
  • 35
  • 427
  • 472