Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am creating an application which will be testable(unit + integration). In this application I have a FileHelper static class,

public static class FileHelper
{
    public static void ExtractZipFile(Stream zipStream, string location)
    {
        ..................................
    } 
    public static void CreatePageFolderIfNotExist(string directory)
    {
        .................................................
    }

    .......................................................
    .......................................................
}

But due to static I think it is not testable. How to make this class testable?

share|improve this question
1  
Why do you think that this class being static makes it not testable? –  Carson63000 Feb 7 '13 at 9:51
    
@Carson63000 because I will not able to mock this. I will using tis clas at lot of places. –  user960567 Feb 7 '13 at 10:04
    
You should not cross-post the same question to multiple sites. Just pick one. –  svick Feb 7 '13 at 11:34
    
@user960567: gotcha, you're talking not so much about testing this class, but testing code which calls this class's static methods? –  Carson63000 Feb 7 '13 at 21:17
    
not really related to the question, but another worry for testing for me would be lots of methods with void returns... –  jk. Feb 8 '13 at 7:39

2 Answers 2

up vote 8 down vote accepted

To say that they're not testable is inaccurate. They're very testable, but they're not mockable and thus they are not test-friendly. That is, every time you test a unit of code that calls this method, you have to test the method. If the method is ever broken, many tests will fail and it won't be obvious why.

With that in mind, the solution is fairly obvious. Make it a non-static class, extract an interface with all the methods in and pass your helper into every class that needs it, preferably through the constructor, and preferably using an IOC Container.

public class FileHelper : IFileHelper
{
    public void ExtractZipFile(Stream zipStream, string location)
    {
        ..................................
    }

    public void CreatePageFolderIfNotExist(string directory)
    {
        .................................................
    }

    .......................................................
    .......................................................
}

public interface IFileHelper
{
    void ExtractZipFile(Stream zipStream, string location);
    void CreatePageFolderIfNotExist(string directory);

    .......................................................
    .......................................................
}

public class MyClass
{
     private readonly IFileHelper _fileHelper;

     public MyClass(IFileHelper fileHelper)
     {
         _fileHelper = fileHelper;
     }
}
share|improve this answer
    
I have also this in mind. But this will create FileHelper instance each time the class which uses this instantiated. Can we overcome this? May be through Singleton? –  user960567 Feb 7 '13 at 10:42
2  
Singletons are also not test-friendly because they persist across tests. If you use an IOC container then it's entirely within your control whether it is instantiated as single-instance or transient (once per object). But ask yourself if it's a problem that needs solving. The GC is very good at disposing of those many helpers, if they're short-lived. –  pdr Feb 7 '13 at 10:46
1  
Yes I am using IOC. I will tell IOC to use single instace. thanks –  user960567 Feb 7 '13 at 10:51
    
@user960567 : Instantiating a class like that is really not expensive. Take a look at this blogpost: ayende.com/blog/4811/performance-numbers-in-the-pub - 7,715,305 instances created in one second. –  Kristof Claes Feb 7 '13 at 11:08
    
+1 for pointing out the difference between testable / test friendly. I would also agree that the overhead of creating multiple instances (in this case, without any actual fields) is pretty small compared to what the zipping will do. –  Daniel B Feb 7 '13 at 11:11

An alternative to pdr's solution is to pass the static function into the class that uses it as a delegate. This allows it to still be mocked out but slightly reduces the amount of boilerplate code

//warning! code not tested
static public class FileHelper 
{
    public static void ExtractZipFile(Stream zipStream, string location)
    {
         //do stuff
    }
}

public class MyClass 
{
    public Action<Stream, string> ExtractZipFile = FileHelper.ExtractZipFile
    public void DoThing()
    {
         //stuff
         ExtractZipFile(mystream, mystring);
         //more stuff
     }
}

MyClassTest()
{
     var target = new MyClass()
     target.ExtractZipFile = (stream, loc) => MaybeVerifSomething(loc);
     target.DoThing();
     //Assert stuff
}
share|improve this answer
    
This tends to be better if you only have a small number of methods in the class that will be used in any one place. If most of the static class need to be used then pdr's answer will be better. –  jk. Feb 7 '13 at 12:08
1  
Given that the example cases seems like a grab-bag utility object, I think this answer is the better approach in the spirit of interface segregation principle. –  Ed Hastings Feb 8 '13 at 0:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.