-1
public class DemoController : Controller
{


    private readonly ICommonOperationsRepository _commonRepo;

    public DemoController (ICommonOperationsRepository commonRepo)
    {
       _commonRepo = commonRepo;
    }
    public ActionResult Default()
    {
       var model = new DemoModel();
       try
       {
           **ConcreteClass cc = new ConcreteClass(Request.ServerVariables["HTTP_X_REWRITE_URL"].ToString());
            cc.ConcreteClassMethod();**

           model.ListTopListing.AddRange(_commonRepo.GetListings());
        }
        catch (Exception ex)
        {
            ExceptionHandler objErr = new ExceptionHandler(ex, "DemoController .Default()\n Exception : " + ex.Message);
            objErr.LogException();
         }
         return View(model);
     }

}

I am trying to unit test my controller. ConcreteClass constructor and its method ConcreteClassMethod both have some dependency on HttpRequest variables which i am not able to pass from my unit tests.

I want a way by which i can simply skip execution of ConcreteClass's constructor and ConcreteClassMethod when I am calling Default action of DemoController.

Sahil Sharma
  • 3,847
  • 6
  • 48
  • 98
  • 1
    You can't create a new instance of an object and stop the constructor from being called. You would have to create an empty parameterless constructor. Either that or re-factor the way that your methods work. You could also inject the value in using Dependency injection. – Luke Nov 30 '15 at 09:57
  • Not sure how to do this. Can you explain this in detail? – Sahil Sharma Nov 30 '15 at 10:05
  • Please see my answer, particularly the last bit that I just added. If you need more info let me know. – Luke Nov 30 '15 at 10:28
  • Please see the amendment. – Luke Nov 30 '15 at 10:36

1 Answers1

0

You can't create a new instance of an object and stop the constructor from being called. You would have to create an empty parameterless constructor.

public class ConcreteClass
{
    private string MyString;

    // Your constructor
    public ConcreteClass(string myString)
    {
        this.MyString = myString;
    }

    // Parameterless constructor
    public ConcreteClass()
    {
        // Do nothing, no code
    }

    // A method that might use MyString
    public void DoSomethingWithMyString()
    {
        var trimmedString = this.MyString.Trim();
    }
}

Either that or re-factor the way that your methods work so that it doesn't rely on having a string passed in on the constructor:

public class ConcreteClass
{        
    // No constructor required anymore

    // Pass the string in to the methods that need the string
    public void DoSomethingWithMyString(string myString)
    {
        var trimmedString = myString.Trim();
    }

    // Pass the string in to the methods that need the string
    public void DoSomethingElseWithMyString(string myString)
    {
        var trimmedString = Int32.Parse(myString);
    }
}

However, that probably doesn't solve the problem, bearing in mind that you want to inject your Request variable and you don't have access to them, can't you just do the following:

public class DemoController : Controller
{
    private string HttpRewriteUrl;

    public DemoController()
    {
        this.HttpRewriteUrl = Request.ServerVariables["HTTP_X_REWRITE_URL"].ToString();
    }

    // Custom constructor for unit testing
    public DemoController(string httpRewriteUrl)
    {
        this.HttpRewriteUrl = httpRewriteUrl;
    }

    public ActionResult Default()
    {
        // Get the value from the object
        ConcreteClass cc = new ConcreteClass(this.HttpRewriteUrl);
        cc.ConcreteClassMethod();
    }
}

Now within your Unit Tests you can use the second constructor and pass the value in:

var controller = new DemoController("your value to pass in here");
controller.Default();
Luke
  • 22,826
  • 31
  • 110
  • 193
  • The problem is that cc.ConcreteClassMethod() also access some Request variables which i want to avoid. – Sahil Sharma Nov 30 '15 at 10:40
  • I'd recommend passing them all in as parameters from your controller in the same way. You'll find that it gives you more clarity as to what the methods do if you pass in the respective values. – Luke Nov 30 '15 at 11:10