Search code examples
c#unit-testinghttpcontext

Fake HttpContext.Current.Server.MapPath for unit test


I have a test which fails on this line. I've figured out that it is because of the HttpContext inside of my GetProofOfPurchase method. Here is the line I'm failing on:

var image = Image.GetInstance(HttpContext.Current.Server.MapPath(GlobalConfig.HeaderLogo));

This is my test:

 [Test]
    public void GetProofOfPurchase_Should_Call_Get_On_ProofOfPurchaseRepository()
    {
        string customerNumber = "12345";
        string orderNumber = "12345";
        string publicItemNumber = "12345";

    var result = new ProofOfPurchase();
    this.proofOfPurchaseRepository.Expect(p => p.Get(new KeyValuePair<string,string>[0])).IgnoreArguments().Return(result);
    this.promotionTrackerService.GetProofOfPurchase(customerNumber, orderNumber, publicItemNumber);
    this.promotionTrackerRepository.VerifyAllExpectations();
}

The test fails on promotionTrackerService.GetProofOfPurchase line. How do I fake the HttpContext in this situation? I have searched Stack Overflow for similar issues to mine but I'm unable to get anything to work.

I've tried doing this:

var image = Image.GetInstance(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, GlobalConfig.HeaderLogo));

But it fails saying:

System.Net.WebException : Could not find a part of the path 'C:\Images\HeaderLogo.png'.

From what I've read on Stack Overflow I shouldn't be using HttpContext.Current if I plan to unit test it, which is why I have tried using Path.Combine, but I'm unable to get that to work properly.

Can someone offer some guidance to what I need to do to get this unit test to work?

Thank you!


Solution

  • What I prefer to do when writing tests for code involving non-pure functions is to hide them behind, in simplest cases, plain old Func<string, string>:

    class PromotionTrackerService
    {
        private readonly Func<string, string> imageMapper;
    
        public PromotionTrackerService(Func<string, string> imageMapper)
        {
            this.imageMapper = imageMapper ?? HttpContext.Current.Server.MapPath;
        }
    
        public void GetProofOfPurchase()
        {
            var image = Image.GetInstance(imageMapper(GlobalConfig.HeaderLogo));
        }
    }
    

    Now, your test does not look like a unit test -- it's more of an integration test, with all that file access and all.