简体   繁体   中英

Mocking an implementation class with test class within unit test in C#

I'm trying to write a simple unit test where I have wrapped the HttpContext.Current.Server.MapPath with an interface and implementation. I'm not positive if the implementation is in the right place.

public class FooGenerator
{
    ServerPathProvider serverPathProvider = new ServerPathProvider();

    public string generateFoo()
    {
        BarWebService bws = new BarWebService(serverPathProvider.MapPath("~/path/file"));
        return stuff;
    }
}


public class ServerPathProvider : IPathProvider
{
    public string MapPath(string path)
    {
        return HttpContext.Current.Server.MapPath(path);
    }
}

In the test I have my own implementation I want to use, but I cannot figure out how to inject this into the real class during the unit test.

[TestClass()]
public class FooGeneratorTests
{
    [TestMethod()]
    public void generateFooTest()
    {
        FooGenerator fg = new FooGenerator();

        //Some kind of mock dependency injection
        Mock<IPathProvider> provider = new Mock<IPathProvider>();
        //stub ServerPathProvider object with provider mock

        string token = fg.generateFoo;
        Assert.IsNotNull(token);
    }
}

public class TestPathProvider : IPathProvider
{
    public string MapPath(string path)
    {
        return Path.Combine(@"C:\project\", path);
    }
}

Finally, here is my interface just in case. Basically I just want to swap out two implementations depending on whether or not I am unit test. This is my first unit test so much of this is new to me. Sorry if I'm missing something basic, but I've been digging through stack overflow for a while now and can't find the steps to do this part.

public interface IPathProvider
{
    string MapPath(string path);
}

There are a few options.

Accepting parameters

In general, you want your FooProvider to have a IPathProvider instead of ServicePathProvider as its servicePathProvider member variable.

You can have two constructors for FooProvider :

  1. A default constructor that instantiates servicePathProvider = new ServicePathProvider(); , and
  2. A non-default constructor that instantiates takes in a IServiceProvider as an argument and sets servicePathProvider to that.

Generic classes

Change FooProvider as follows:

public class FooProvider<T> where T : IServiceProvider, new()

In non-unit testing code, you would use FooProvider<ServicePathProvider> and for unit tests, you would use FooProvider<Mock> .

This makes FooProvider accepts a generic type T which is a subtype of IServiceProvider and has a default constructor (that's the new() part) in the where clause.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM