Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making methods 'internal' to remove dependencies (for unit tests) - a good practice? Any better way?

I have a class as follows.

public class MyClass  
{  
    public MyMethod()  
    {  
      int x = CalculateSomething();  
    }

   private int CalculateSomething()  
   {  
      // Do something and return an int    
      return 100;  
   }  
}  

To unit test this I added [assembly: InternalsVisibleTo("MyTests")] and changed the private method to be internal virtual. In the unit test project I created a class MockMyClass and created private method as follows.

public class MockMyClass : MyClass  
{  
   public bool MadeHappyNoise {get; set;}
   internal override int CalculateSomething()  
   {  
      MadeHappyNoise = true;  
      return base.CalculateSomething();  
   }  
}

The unit test is now as follows

[TestMethod()]
public void WasCalculateSomethingCalledOK()  
{  
   MockMyClass mk = new MockMyClass();
   mk.MyMethod();  
   Assert.IsTrue(mk.MadeHappyNoise, "Oops...CalculateSomething not called...");  
}  

Few questions: Is this is a good way to remove dependencies? I personally don't like to change a method from private to internal but have no option (other than to use Reflection perhaps). Also, the attribute InternalsVisibleTo("MyTests") residing in the production code is not good. Can someone point me to a better solution please? Thanks.

like image 602
Redzon Avatar asked Oct 14 '22 17:10

Redzon


2 Answers

It rather depends on the methods you are changing the scope of. A unit is the smallest testable component of a piece of software - it rarely means one test per method.

I find that comprehensively testing my public methods is enough to establish correct behaviour. You might find that your tests start to constrain your code development if you wrap the private methods with tests.

If your program is more procedural you might find that you need to test at the granular level you describe, in which case using friend assemblies is a fine solution. However, I'd suggest that you would rarely need to test methods that aren't public.

like image 129
David Neale Avatar answered Feb 26 '23 21:02

David Neale


Too much work for too little value. All that test tells me (if it passes) is that calling MyMethod calls another private method. The unit test should be testing the behavior provided by MyMethod() - what should happen/change after a call to MyMethod?.

The title of the question is a bit misleading too - there is no dependency-related issue that I can see.

You do not need InternalsVisibleTo for the most part.. simply test the private method through the public method that exercises it e.g. Write unit tests for MyMethod(). Also if you practice test-first programming, you'd already have tests that cover every line of code in the private method.

like image 20
Gishu Avatar answered Feb 26 '23 21:02

Gishu