0

I am experiencing an issue during Testing. I have a class and properties like these ones

 public class ViewModel {

 ....

   public string Person 
    {
        get
        {
            return _person;
        }
        set
        {
            if (_person != value)
            {
                _person = value;
                RefreshStrategy();
                OnPropertyChanged();
                Somefield = string.Empty;
            }
        }
    }

   public BindingList<string> Strategies
    {
        get
        {
            return _lstStrategies;
        }
    }

Now RefreshStrategy, which is a huge method with several other objects, takes some strategies from a database and updates _lstStrategies according to the Person selected. Now everything is working fine on runtime but when I try to test it, I have an issue:

[TestClass]
public class ViewModelTest 
{

    private ViewModel _viewobj; 

    public ViewModelTest()
    {

        _viewobj = new ViewModel();
    }


    [TestMethod]
    public void TestStrategies()
    {
       _viewobj.Person = "Test";

        Assert.AreEqual("AAAA", _viewobj.Strategies[0]); 

    }

 private void RefreshStrategies()
    {
         Logger.log(Logger.INFO, $"GOT STRATEGIES");
        // Reload these default options every time the form loads, in case    some applications settings have been changed
        if (String.IsNullOrEmpty(Trader) && !SettingsMgr.IsCompositePortfolio)
        {
            Person = Utility.SettingsMgr.PORTFOLIO_CODE;
        }
        if (!String.IsNullOrEmpty(Person))
        {

            string fund = _portfolios.Where((tt) => tt.PersonId == Person).Select(tt => tt.Fund).FirstOrDefault();
            if (!string.IsNullOrEmpty(fund))
            {
                fund = "X";
            }
            var profitCenters = new List<ProfitCenter>();
            try
            {
                Logger.log(Logger.INFO, $"Try to load strategies for {Person} {fund}");

                var pci = DataMgr.getInstance().GetProfitCenterInfo(Person, fund);
                Logger.log(Logger.INFO, $"HERE !!!");
                profitCenters = pci?.profitCenters;

            }
             ......

      }

When I set Person = "Test", obviously RefreshStrategy() is called but inside all objects are null and it raises the exception "...attempt to dereference a null object reference". The simple Logger at the beginning is raising and if I comment it out Utility.Setting is reasing and so on

If I do a trivial test on this class like testing a simple variable is passing and this is telling me that all references in the test project are fine.

What am I doing wrong? Do I mock the entire method? And if yes how if it is private?

4
  • 1
    Please post the RefreshStrategy function. Commented Sep 7, 2017 at 17:40
  • 5
    Move RefreshStrategy into separate class. Create interface for it and then you can simply mock the interface. Commented Sep 7, 2017 at 17:44
  • @Nkosi my question is to understand if I need to mock it or it is null because I am missing something during test Commented Sep 7, 2017 at 17:55
  • @Nkosi I will try to reproduce it in a small example. Commented Sep 7, 2017 at 18:01

1 Answer 1

1

This is one way to go:

public interface IStrategyManager 
{
    void RefreshStrategy();
}
public class StrategyManager : IStrategyManager
{
    public void RefreshStrategy()
    {
         // Doesn't matter what is in here.
    }
}
public class ViewModel {
    public IStrategyManager StrategyManager = new StrategyManager();

   public string Person 
    {
        get
        {
            return _person;
        }
        set
        {
            if (_person != value)
            {
                _person = value;
                StrategyManager.RefreshStrategy();
                OnPropertyChanged();
                Somefield = string.Empty;
            }
        }
    }
}

You just need to mock the property:

private ViewModel _viewModel;

[Test]
public void Test()
{
    _viewModel = new ViewModel
    {
        StrategyManager = new Mock<IStrategyManager>().Object,
        Person = "whatever"
    };

}

Of course it would work even better with Dependency Injection, but I don't know if you are using it. Then you could replace property with constructor injection.

This also allows you to have different implementations of IStrategyManager, which is nice. The weak point of this approach is additional class and interface.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.