Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I mock a base method from the Controller class using the NSubstitue framework

I need a mock a method present in a base class when an Action method in the Controller class invoke it.

Here is my Controller class below, the action method Index() calls the base method GetNameNodeStatus(). Now how can I mock the GetNameNodeStatus() present in the base class when the action method Index calls it using the Nsubstitute mocking frameworks.

using Cluster.Manager.Helper;
using Cluster.Manager.Messages;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;

namespace Cluster.Manager
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            ClusterMonitoring monitoring = new ClusterMonitoring();
            string getStatus = monitoring.GetNameNodeStatus("", new Credential());
            return View();
        }
     }
}

Here is my base class Clustermonitoring

namespace Cluster.Manager.Helper
{
    public class ClusterMonitoring
    {
        public virtual string GetNameNodeStatus(string hostName, Credential credential)
        {
            return "Method Not Implemented";
        }
    }
}

And here is my Test class

namespace NSubstituteControllerSupport
{
    [TestFixture]
    public class UnitTest1
    {

        [Test]
        public void ValidateNameNodeStatus()
        {
            var validation = Substitute.ForPartsOf<ClusterMonitoring>();
            validation.When(actionMethod => actionMethod.GetNameNodeStatus(Arg.Any<string>(), Arg.Any<Credential>())).DoNotCallBase();
            validation.GetNameNodeStatus("ipaddress", new Credential()).Returns("active");
            var controllers = Substitute.For<HomeController>();
            controllers.Index();
        }
    }
}
like image 585
Kumaran Raj K Avatar asked Nov 09 '22 02:11

Kumaran Raj K


1 Answers

ClusterMonitoring is being created in the method manually.

ClusterMonitoring monitoring = new ClusterMonitoring();

This means that substituting it is not possible. you need to inject ClusterMonitoring as a dependency to the controller in order to have the ability to substitute it out when testing.

First abstract ClusterMonitoring behind an interface

public interface IClusterMonitoring  {
    string GetNameNodeStatus(string hostName, Credential credential);
}

and have it inherit that interface

public class ClusterMonitoring : IClusterMonitoring {
    public virtual string GetNameNodeStatus(string hostName, Credential credential) { ... }
}

Update controller to take dependency via constructor

public class HomeController : Controller {
    private readonly IClusterMonitoring monitoring;

    public HomeController(IClusterMonitoring monitoring) {
        this.monitoring = monitoring;
    }

    // GET: Home
    public ActionResult Index() {
        var status = monitoring.GetNameNodeStatus("", new Credential());
        return View(status);
    }
 }

Now update test to inject dependency into controller under test

[TestFixture]
public class UnitTest1 {

    [Test]
    public void ValidateNameNodeStatus() {
        //Arrange
        var expected = "active";
        var validation = Substitute.For<IClusterMonitoring>();
        validation.GetNameNodeStatus("", new Credential()).Returns(expected);
        var controller = new HomeController(validation);

        //Act
        var actual = controllers.Index() as ViewResult;

        //Assert
        Assert.IsNotNull(actual);
        Assert.AreEqual(expected, actual.Model); 
    }
}
like image 166
Nkosi Avatar answered Nov 14 '22 21:11

Nkosi