Search code examples
c#unit-testingxunit

When testing a controller method how should you handle the scenerio when it calls a local method


I am using xUnit testing against a WebAPI controller. I have the following methods in my controller:

public string GetLoginMessage()
{
  var loginMessage = GetSystemSetting("LoginMessage", "Retrieving...");
  return loginMessage;
}

public string GetOwnerName()
{
  string ownerName = GetSystemSetting("OwnerName", "Retrieving...");
  return ownerName;
}

private string GetSystemSetting(string SettingName, string DefaultValue)
{
  var settingValue = DefaultValue;
  //var _systemSettingsBL = new SystemSettingsBL();
  var systemSettingInfoList = _systemSettingsBL.GetSystemSettings(0, 0);
  var setting = systemSettingInfoList.Where(w => w.Key == SettingName).FirstOrDefault();
  if (setting != null && string.IsNullOrWhiteSpace(setting.Value) == false)
  { settingValue = setting.Value; }
  return settingValue;
}

As you can see GetSystemSettings() gets called multiple times from various methods in the same controller.

I'm using a simple example here with GetLoginMessage() and GetOwnerName(). Is my logic right in assuming these three methods should be tested separately in isolation? If so, wouldn't I need to mock GetSystemSettings(). If so, how do I go about doing that?

My test thus far:

  public class AccountsControllerTests : BaseUnitTest
  {
    private readonly Mock<ICommonBL> _commonBLMock;
    private readonly Mock<ISystemSettingsBL> _systemSettingsBLMock;
    private readonly AccountsController _accountsController;

    public AccountsControllerTests()
    {
      _commonBLMock = new Mock<ICommonBL>();
      _systemSettingsBLMock = new Mock<ISystemSettingsBL>();
      _accountsController = new AccountsController(_commonBLMock.Object, _systemSettingsBLMock.Object);
    }

    [Fact]
    private void GetLoginMessage_ShouldReturnString_WhenCalled()
    {
      //how to possibly mock local controller method GetSystemSetting()

      var loginMessage = _accountsController.GetLoginMessage();

      Assert.NotNull(loginMessage);
      Assert.IsType<string>(loginMessage);
    }
  }

Solution

  • Your test scenario depends on _systemSettingsBL.GetSystemSettings to have data and validation of it. So you should be focusing mocking it which you can do by defining setup method of GetSystemSettings on _systemSettingsBLMock. With that you can add the assert on loginMessage based on your mock data.

    In your test method GetLoginMessage_ShouldReturnString_WhenCalled, setup like below

    _systemSettingsBLMock.Setup(
               s => s.GetSystemSettings(It.IsAny<int>(), It.IsAny<int>())
               .Returns( //return here the mock object of systemSettingInfoList which contains LoginMessage settingName  );