Skip to content

Instantly share code, notes, and snippets.

@nathanwoulfe
Created April 12, 2021 23:57
Show Gist options
  • Save nathanwoulfe/84f94e6ac890c4c57c7594214a700a4c to your computer and use it in GitHub Desktop.
Save nathanwoulfe/84f94e6ac890c4c57c7594214a700a4c to your computer and use it in GitHub Desktop.
Mock IUmbracoContextFactory
private readonly IUmbracoContextFactory _context;
private readonly string _pluginPath;
public LicensingService(ILogger logger, IUmbracoContextFactory context) : base(logger)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
_pluginPath = $"{IOHelper.ResolveUrl(SystemDirectories.AppPlugins).TrimEnd('/')}/plumber/";
}
public Tuple<string, string> GetLicenseAndKey() {
using (var cref = _context.EnsureUmbracoContext())
{
// under test, with a mocked _context, HttpContext and Server are null (which is expected). I don't really want to mock all the way down,
// because the context factory is a pretty large, complex object
var keyPath = cref.UmbracoContext.HttpContext.Server.MapPath($"{_pluginPath}plumber.key");
// instead, I think this would work fine, and remove the need for the factory entirely
// HttpContextManager is mine, and can be mocked
var licPath = HttpContextManager.Current.Server.MapPath($"{_pluginPath}plumber.lic");
// other stuff happens here which is irrelevant to the mocking issue...
}
}
@Adolfi
Copy link

Adolfi commented Apr 13, 2021

Hi. Are you looking to test if the .key file actually exists in that location (integration testing) or mocking the MapPath?

@nathanwoulfe
Copy link
Author

Just need to mock MapPath, which is straightforward on the HttpContextManager object as it's pretty slim compared to UmbracoContextFactory. I think I can swap out one for the other with no issues (can't see any reason I wouldn't have context, or why I ever needed the factory in the firsts place)

That said, I think there are a couple of other places in the codebase where I do need the factory, so any advice around how to efficiently mock it, would be awesome

@Adolfi
Copy link

Adolfi commented Apr 14, 2021

Yeah I agree, in most cases where I need to access a physical file I usually have some sort of IFileHelper that accesses Server MapPath behind the scenes and I can just mock the interface in my tests. Like you are doing with your HttpContextManager. So probably go with that with both the .key and .lic file.

Agree, still good to figure out how to mock the factory properly and I'll be glad to help out.

Great then I wont focus on the MapPAth but instead I will try to see if it's possible to just mock the UmbracoContext and HttpContext returned from EnsureUmbracoContext().

To be continued...

@Adolfi
Copy link

Adolfi commented Apr 14, 2021

I Nathan.
I just looked at this and I would say you cant mock this.
The .EnsureUmbracoContext returns a concrete type UmbracoContextReference which has an internal constructor.
Would have liked to see some sort of Interface like IUmbracoContextReference being returned but sadly its not. :(

@Adolfi
Copy link

Adolfi commented Apr 15, 2021

You could create your own abstraction layer on top of the UmbracoContextFactory, kind of like you've done with the HttpContextManager.
I also started experimenting with Reflections to get a test running but it seems a bit dirty and the test wont really match the reality so whats the point really? Probably just best to create a PR to Umbraco to make .EnsureUmbracoContext() testable.

@nathanwoulfe
Copy link
Author

Thanks Dennis, really appreciate your time. Might have to start nagging HQ to do make more ctors public

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment