Setting private member variable

8 posts, 0 answers
  1. Jiti
    Jiti avatar
    12 posts
    Member since:
    Jul 2012

    Posted 22 Oct 2012 Link to this post

    What is the just mock equivalent of setting the value of a private member variable?

    public class foo
    {
    private IEventAggregator _ea;
    ...
    }

    I just want to do something like this:

    foo mockedFoo = Mock.Create<foo>();
    IEventAggregator fakeEA = Mock.Create<IEventAggregator>();
    Mock.NonPublic.Arrange(foo, "_ea", fakeEA);

    But this is not working for me and gives me an error:
    System.ArgumentException: Could not resolve the target method; make sure that you have provided arguments correctly.
  2. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 23 Oct 2012 Link to this post

    Hi Jiti,

     Thank you for contacting Telerik support.

     In order to fake the returning value of a non-public property/member, you will have to arrange against it`s "get" function.

     Let`s assume we have the following class with it`s private members:
     
    public interface IEventAggregator
    {
        string firstProp { get; set; }
        int secondProp { get; set; }
    }
     
    public class Foo
    {
        private IEventAggregator myInterfaceWithSet { get; set; }
        private string myStringWithGet { get; set; }
     
        public string ReturningMyInterface()
        {
            return myInterfaceWithSet.firstProp;
        }
     
        public string ReturningMyString()
        {
            return myStringWithGet;
        }
    }

     There are couple of examples that I have prepared about your issue:

    1. We will fake the string property:
      [TestMethod]
      public void ShouldReturnFakeStringWithGetFunction()
      {
          var mockedFoo = Mock.Create<Foo>(Behavior.CallOriginal);
       
          string expected = "telerik";
       
          //arrange
          Mock.NonPublic.Arrange<string>(mockedFoo, "myStringWithGet").Returns(expected);
       
          //act
          string actual = mockedFoo.ReturningMyString();
       
          //assert
          Assert.AreEqual(expected, actual);
      }
      You can see that we are arranging that our property is returning a certain value when called.

    2. Faking an interface private member is almost the same. The only difference here is that we need to create a mocked instance of our class/interface with the wanted parameters:
      [TestMethod]
      public void ShouldMockPrivatePropertyWithGetFunction()
      {
          var mockedFoo = Mock.Create<Foo>(Behavior.CallOriginal);
          var mockedIEA = Mock.Create<IEventAggregator>();
       
          mockedIEA.firstProp = "telerik";
          mockedIEA.secondProp = 55;
       
          //arrange
          Mock.NonPublic.Arrange<IEventAggregator>(mockedFoo, "myInterfaceWithSet").Returns(mockedIEA);
       
          //act
          string actual = mockedFoo.ReturningMyInterface();
       
          //assert
          Assert.AreEqual("telerik", actual);
      }

     I hope this solves your issue. If I can help you with anything else, please do not hesitate to ask.

    Regards,
    Kaloyan
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. DevCraft R3 2016 release webinar banner
  4. Jiti
    Jiti avatar
    12 posts
    Member since:
    Jul 2012

    Posted 23 Oct 2012 Link to this post

    Thank you for your reply.
    It does work when there is a property or function that sets the member variable. But my production code does not need a setter, it gets set in the constructor. Writing a setter just so that the member variable can be mocked did not seem right. That was why I was wondering if it was possible to set the value of the member variable directly.

    For e.g. if I do this,

    var realFoo = new foo();
    PrivateObject po = new PrivateObject(realFoo);
    po.SetField("_ea", fakeEA);   // This works (But I need to used a mocked version of foo so in that case po.SetField does not work)

    Is there something similar to the above SetField method in JustMock or is it only possible if there is a setter or a method that sets its value, like in the solution proposed?

    Thanks,
    Jiti
  5. Jiti
    Jiti avatar
    12 posts
    Member since:
    Jul 2012

    Posted 23 Oct 2012 Link to this post

    I just checked and looks like just having a private setter does not work. It needs to be a private method that takes an argument.

    So if the production code had the property
    private IEventAggregator EventAggregator { get; set; }
    then in the test case,
    Mock.NonPublic.Arrange(foo, "EventAggregator", fakeEA);
    does not work!

    But if the production code had the method
    private void SetEventAggregator(IEventAggregator ea)
    {
    _ea = ea;
    }
    then in the test case,
    Mock.NonPublic.Arrange(foo, "SetEventAggregator", fakeEA);
    works!

    I wonder why it does not work with private property.

    Thanks,
    Jiti

  6. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 24 Oct 2012 Link to this post

    Hi Jiti,

     Thank you for coming back to us.

     As I can understand from your first reply, you are trying to fake datum. Unfortunately this is not possible in JustMock, neither in other mocking tools. What our product is expected to do is to fake an object by mocking its behavior.

     For example: You create a fake class, so that you can comfortably arrange the new behavior of its functionality, or methods.

     However, as I noted above, mocking or faking datum is not directly allowed. Nevertheless, there are ways and principles in programming that can permit you, fake the value of a certain variable. One of them, I would recommend, is the using of a property, that is acting directly with your private member variable. Having such, you can easily mock its get or set function, so that it returns or takes a certain data. 
     
     Let`s assume you are having this "SomeClass" class. 
    class SomeClass
    {
        public SomeClass()
        {
            _myProperty = 123;
        }
     
        public int _myProperty;
     
        public int MyProperty
        {
            get { return this._myProperty; }
            set { this._myProperty = value; }
        }
    }
    As you can see there is a member variable "_myProperty", that is taking its value inside the constructor. The mandatory here is that, we have a property "MyProperty", that can show or change the variable`s value. From now on, it is good to use 'MyProperty', instead of "_myProperty", to cover the rest of "SomeClass" functional logic. If we continue to the testing part, you will notice that, now it is very easy to fake the whole behavior of our class:
    [TestMethod]
    public void TestMethod1()
    {
        var mock = Mock.Create<SomeClass>();
     
        // Arrange
        Mock.Arrange(() => mock.MyProperty).Returns(321);
     
        // Act
        var actualValue = mock.MyProperty;
        var origValue = mock._myProperty;
     
        // Assert
        Assert.AreNotEqual(actualValue, origValue);
        Assert.AreEqual(321, actualValue);
        Assert.AreEqual(123, origValue);
    }

     As for your second concern, I must say that you are right. Having a private setter won`t let you fake the returning value. You will need a private property with both get and set functions, or atleast with a getter, so that you can arrange that function to return the desired value, the same way, as you are arranging methods for example:
    Mock.NonPublic.Arrange<IEventAggregator>(foo, "EventAggregator").Returns(fakeEA);
     Note that, you will need to specify the property type ("<IEventAggregator>") first. Then you have to point the previously mocked class/interface ("foo") with its property/method you would like to arrange against ("EventAggregator"). Finally you need to fake its get function, so that it returns your "fakeEA", instead of the original value (".Returns(fakeEA)").

     I hope you will find this information useful and it will lead you to solving you issue. Please, let me know if I can be helpful with anything else.

    Regards,
    Kaloyan
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  7. Chuck
    Chuck avatar
    7 posts
    Member since:
    Feb 2012

    Posted 01 Feb 2013 Link to this post

    I'd like to follow up on this, which seems to me a major failing (inability to mock a private member variable). Consider the following

    public class TM
    {
        private Task m_ActiveTask = null;
        // provide readonly access to the world
        public Task ActiveTask
        {
            get { return m_ActiveTask;}
        }
        // let users set the Active task, which is a complicated operation, NOT just an assignment to internal variable
        public void SetActiveTask (string sTaskName)
        {
            // lots of complicated manipulations, including
            Task oNewTask = new Task(...);
            //finally resulting in
            m_ActiveTask = oNewTask;
        }
        // later, another function may need to test whether any task is active
        public void Cleanup()
        {
            if(null != m_ActiveTask)
            {
                // do some cleanup, then
                m_ActiveTask = null;
            }
        }
    }

    Now, I want to write a unit test for Cleanup. Obviously, I need to put a Mocked Task object in m_ActiveTask. But it is a private member variable.
    Obviously, I do not want to expose it as public. I have good and sound reasons for maintaining within TM the ability to SET the variable, and not to allow the casual caller to mess with it.
    How does one proceed in this situation?
    Let's assume JustMock JustWon't allow me to set the member variable directly (see how I JustMade that little joke? :), and that I'm willing to refactor my code so that class methods always access via the property, thus:

        public void Cleanup()
    {
         if(null != ActiveTask) // use property
         {
             // do some cleanup, then
             m_ActiveTask = null;
         }
    }

    If I then define my property THIS way, is there some way to get it JustRight?

    public Task ActiveTask
    {
        get { return m_ActiveTask; }
        private set { m_ActiveTask = value; } // make setter private to the class
    }

    Thanks.
    (btw, Jiti, is a co-worked of mine, and we are working on different parts of the same product)
  8. Chuck
    Chuck avatar
    7 posts
    Member since:
    Feb 2012

    Posted 01 Feb 2013 Link to this post

    Nevermind.
    If I'm willing to refactor to use the property in the TM class, of course I can sufficiently mock a .Returns on the property.
    I still believe the ability to set private member variables will be sine qua non for comprehensive test coverage. There will be times when the state of private member variables that are PURELY private, and need NO exposure, will determine code path execution. Requiring the programmer to make them private *properties* rather than member variables is just silly.
  9. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 05 Feb 2013 Link to this post

    Hello Chuck,

    Thank you for the detailed feedback.

    You are correct that such feature will definitely enrich JustMock. 

    I would suggest you using our Ideas and Feedback portal, so that other clients could also vote for its implementation in our product. 

    Kind regards,
    Kaloyan
    the Telerik team
    Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
Back to Top
DevCraft R3 2016 release webinar banner