1

I am writing Unit tests for the following class legacy class

Class myLegacyClassPresenter
{
  private MethodA(){}
  private propertyA {get; set;}
  private MethodB(YearValue value){}

 //some more properties & method goes here

 private struct YearValue
 {
    public static int One { get { return 365; } }
    public static int Two { get { return 730; } }
 } 
}

Here is my unit test.

public void mytest()
{
 //some initializations
 var view = myLegacyView();
 var service = new Mock<ILegacyService>();
 var presenter = new myLegacyClassPresenter(view, service);
 var privateObject = new PrivateObject(presenter);

 //I can access all private methods and properties as follows
 privateObject.invoke("MethodA");
 privateObject.GetProperty("propertyA")

// But How can I get the the Struct Year value to pass to MethodB
privateObject.Invoke("MethodB", new object[]{YearValue.One}); //Compile Error for YearValue 

//I can't change in the class, One way is to define the same struct locally, Is there any other approach we can have to achieve the same result.
}
Haseeb Asif
  • 1,766
  • 2
  • 23
  • 41
  • 1
    Is `YearValue` a parameter to `MethodB`? If so, your code won't compile regardless of your unit tests (it's error [CS0050](http://msdn.microsoft.com/en-us/library/be25s2h2.aspx)). – Patrick Quirk May 19 '14 at 12:33
  • @PatrickQuirk Thanks for pointing that out, Just updated it. – Haseeb Asif May 19 '14 at 13:34
  • 2
    You may want to consider [testing the public interface that will be used rather than testing private methods and properties](http://stackoverflow.com/q/105007/299327). – Ryan Gates May 19 '14 at 13:46
  • I agree with @RyanGates, but at the moment I am just updating the old unit tests which was using the depreciated method of accessing private methods `myLegacyClassPresenter_PrivateAccessor' to `PrivateObject` – Haseeb Asif May 19 '14 at 13:58
  • It may be a typo but the MethodB take a YearValue but you are trying to invoke it passing in a int (YearValue.One). I have an answer below that shows how to pass in YearValue. If you need to pass in the int YearValue.One you can use reflection to get the value from the type obtained in the answer – AlanT May 20 '14 at 11:53

2 Answers2

0

Classic example which shows how if you cannot unit test a particular component, REFACTOR the component!

This is where is love what any mocking framework enforces you to do - write decoupled code.

Couple of things:

  1. Testing private methods should be seriously reconsidered. You break encapsulation the moment you test private methods and properties.

  2. In your example, the myLegacyClassPresenter class is very tightly coupled with the YearValue struct. You could decouple it using dependency injection.

Amol
  • 3,977
  • 1
  • 23
  • 24
0

If you want to create an instance of the struct you can use something like the following

var theType = Type.GetType("MyNamespace.myLegacyClassPresenter+YearValue");
var parameter = Activator.CreateInstance(theType);

privateobject.Invoke("MethodB", new object[]{parameter});

If you need to pass in YearValue.One, then theType.GetMember() can be used to get the value.

AlanT
  • 3,627
  • 20
  • 28