简体   繁体   中英

NSubstitute Mock static class and static method

I'm new at unit testing, and I'm trying to mock a static method in a static class. I already read that you can't do that, but I was looking a way to work around that.

I can't modify the code, and making the same function without being static is not an option because they check the code coverage of the test, and I need at least 90%.
I already tried to mock the variables that it uses but it doesn't work.

public static class MyClass
{
    public static response MyMethod(HttpSessionStateBase Session, 
        otherVariable, stringVariable)
    {
        //some code
    }
}

public ActionResult MyClassTested()
{
    var response = MyClass.MyMethod(Session);
    //more code
}

My problem is that this method is inside a controller that declares a var with the response, and according to that redirects the user.

If you can't modify the code then I don't think it is possible to work around this using DynamicProxy-based libraries like NSubstitute. These libraries use inheritance to intercept members on classes , which is not possible for static and non-virtual members.

I suggest trying Fakes . One of the examples on that page covers stubbing DateTime.Now .

Other alternatives that can mock static members include TypeMock and Telerik JustMock.

Related question: https://stackoverflow.com/q/5864076/906

There could be a nicer solution to this sort of problem... depending on what you can get away with.

I recently ran into this myself after having written a static utility class used to, essentially, create various truncations of the Guid format. While writing an integration test, I realized that I needed to control a random Id that was being generated from this utility class so that I could deliberately issue this Id to the API and then assert on the result.

The solution I went with at the time was to provide the implementation from a static class, but call that implementation from within a non-static class (wrapping the static method call), which I could register and inject in the DI container. This non-static class would be the main workhorse, but the static implementation would be available in instances where I needed to call these methods from another static method (for example, I had written a lot of my integration setup code as extensions on IWevApplicationFactory, and used the static utility to create database names).

In code, eg

// my static implementation - only use this within other static methods when necessary. Avoid as much as possible.
public static class StaticGuidUtilities 
{
    public static string CreateShortenedGuid([Range(1, 4)] int take)
    {
        var useNumParts = (take > 4) ? 4 : take;
        var ids = Guid.NewGuid().ToString().Split('-').Take(useNumParts).ToList();
        return string.Join('-', ids);
    }
}


// Register this abstraction in the DI container and use it as the default guid utility class
public interface IGuidUtilities
{
    string CreateShortenedGuid([Range(1, 4)] int take);
}

// Non-static implementation
public class GuidUtitlities : IGuidUtilities
{
    public string CreateShortenedGuid([Range(1, 4)] int take)
    {
        return StaticGuidUtilities.CreateShortenedGuid(take);
    }
}

----

// In the tests, I can use NSubstitute...
// (Doesn't coding to the abstraction make our lives so much easier?)
var guidUtility = Substitute.For<IGuidUtilities>();
var myTestId = "test-123";
guidUtility.CreateShortenedGuid(1).Returns(myTestId);

// Execute code and assert on 'myTestId' 
// This method will call the injected non-static utilty class and return the id
var result = subjectUndertest.MethodUnderTest();

// Shouldly syntax
result.Id.ShouldBe(myTestId);

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