locked
How can i test my MVC Controllers ? RRS feed

  • Question

  • User1253338400 posted

    Hi ,

    I would like ot test my MVC controllers. They arent simple , I have ActionResult that returns a View, But there is alot of code before the View is returned.

    For example I call 

    public ActionResult Login(string returnUrl)

         EnsureLoggedOut();
         var viewModel = new AccountLoginModel
         {
            ReturnUrl = returnUrl
         };
         return View(viewModel);
    }

    When i try to run a simple test it calls EnsureLoggedOut, which in turn looks for  a Request Object which is null. (do i need to Mock that ?).

     I want to test this ActionMethod such that it returns what it is meant to ..

    Is there examples on how to do this or a framework that can help 

    Thanks

    Tuesday, April 16, 2019 6:41 AM

Answers

  • User-474980206 posted

    using request object directly will make testing harder. you will need to mock it in routines that use it. in you sample code it would make more sense to make EnsureLoggedOUt() mockable. make it settable property, with a default implementation.

        public Action EnsureLoggedOut = () =>
       {
          ...
        };

    then in the unit test replace it with a mocked version

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 16, 2019 2:07 PM

All replies

  • User-474980206 posted

    using request object directly will make testing harder. you will need to mock it in routines that use it. in you sample code it would make more sense to make EnsureLoggedOUt() mockable. make it settable property, with a default implementation.

        public Action EnsureLoggedOut = () =>
       {
          ...
        };

    then in the unit test replace it with a mocked version

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, April 16, 2019 2:07 PM
  • User1253338400 posted

    Hi ,

    I not understanding exactly what you mean 

    Maybe I can show with this ..

    I have a test method as follows:          

    [TestMethod]        
    public void GetActionReturnsCustomerAsJson()        
    {            
        CustomerController controller = new CustomerController();                         
        JsonResult result = controller.GetCustomer() as JsonResult;          
        // todo add asserts here.        
    }  

    Now when i debug the testmethod above,  it calls the following controller code:  

    [HttpPost]        
    public ActionResult GetCustomer()        
    {            
    var customer = Customer.Get();            
    return Json(new { success = string.IsNullOrEmpty(customer.Error), customer = customer });        
    }  

    When it calls: var customer = Customer.Get(); it then goes to code below:
    But I have a set Customeid and url that I know and the resultant Customer object that I expect to be returned, but what I cant exactly figure out is if I let the
    code step through  while  debugging GetCustomer doesnt take any inputs , nor does the Get , how can i pass these in ? Also when i get to call Get , Session is null ,
    how can i overcome this ?
    Do i need to set an Initialise routine in my tests ?        

    public static Customer Get()        
    {                             
    var customerId = Principal.Current.ClientId;   <-------This i know I can pass in, but how since there are no input parameters ?                
    var setup = SessionFactory.GetSetup();         <-------This get the db connnection string , do I need to Mock  ?                    
    var authUrl = setup?.AuthenticationUrl ?? ConfigurationManager.AppSettings.GetValues("AuthenticationServer").First(); <-----I actually know the URL required .                  

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{authUrl}customer/{customerId}"); <------This I know from the above URL.                                   
    request.Method = "GET";                
    var response = request.GetResponse();                
    var responseJson = string.Empty;                  
    using (var stream = response.GetResponseStream())                
    {                    
          using (var rdr = new StreamReader(stream))                    
         {                             
              responseJson = rdr.ReadToEnd();                    
         }                
    }                  
    if (string.IsNullOrEmpty(responseJson))                
    {                    
         return new Customer { Error = "No record located." };                
    }                  
         var customer = JsonConvert.DeserializeObject<Customer>(responseJson);                
         if (customer != null)                    
             return customer;                  
        return new Customer { Error = "No record located." };        
    }

    So basically all I want back is  Customer object and I can check what is returned against what I expect.

    Thanks

    Wednesday, April 17, 2019 4:55 AM