Partial Mocking of Private Method not working in large test run

6 posts, 0 answers
  1. Chris
    Chris avatar
    21 posts
    Member since:
    Oct 2012

    Posted 03 Jun 2011 Link to this post

    I have a similar issue to http://www.telerik.com/community/forums/justmock/general-discussions/mocks-failing-to-work-correctly-in-large-test-runs.aspx

    I have the following code:
    ClassInitialize Method
    [ClassInitialize()]
           public static void MyClassInitialize(TestContext testContext)
           {
               
    		 Mock.Partial<EagleUtility>().For(() => EagleUtility.ValidateMessage(Arg.IsAny<byte[]>(), Arg.AnyIntTowerTypes.Unified));
               	 Mock.Partial<UnifiedProtocolTranslator>();
    
           }

    TestMethod
    public void RecieveIncomingMessageTest()
            {
                var expectedTower = TestContext.DataRow["Tower"].ToString();
                var expectedEventDescription = TestContext.DataRow["EventDescription"].ToString().TrimStart('\r''\n'' ');
                expectedEventDescription = expectedEventDescription.TrimEnd(' ''\n''\r''\0');
                var rawDataToUse = Convert.FromBase64String(TestContext.DataRow["RawData"].ToString());
                var called = false;
                var target = new UnifiedProtocolTranslator();
                ;
                int byteCount = rawDataToUse.Length;
                EagleIncomingMessageStatus expected = EagleIncomingMessageStatus.Complete;
                EagleIncomingMessageStatus actual;
     
                
     		   Mock.NonPublic.Arrange<bool>(target, "ProcessIncomingMessage", rawDataToUse, 0).IgnoreArguments().DoInstead((byte[] arg1,int arg2) => called =true).Returns(true).MustBeCalled();
              
                Mock.NonPublic.Arrange(target, "CompileIncomingMessage").DoNothing().MustBeCalled();
                actual = target.RecieveIncomingMessage(rawDataToUse, byteCount);
     
                Mock.Assert(target);
      
     
                Assert.AreEqual(expected, actual);
            }


    Method Being Tested.

    public EagleIncomingMessageStatus RecieveIncomingMessage(byte[] message, int byteCount)
           {
               var messageType = (UnifiedIncomingMessageTypes) message[0];
               EagleIncomingMessageStatus returnValue = EagleIncomingMessageStatus.Continue;
               if (EagleUtility.ValidateMessage(message, byteCount, TowerTypes.Unified))
               {
                   if (ProcessIncomingMessage(message, byteCount))
                   {
                       CompileIncomingMessage();
                       returnValue = EagleIncomingMessageStatus.Complete;
                   }
               }
     
               return returnValue;
           }

    When I run the RecieveIncomingMessageTest method on it's own everything passes as it should.  However when I run it as part of the larger test run that test method fails.

    I am sure it is because I have a test method that tests the actual funtionality of ProcessIncomingMessage in the same test class( because they are methods in the same concrete class).

    How can I mock the ProcessIncomingMessage method for the RecieveIncomingMessageTest method but not for the ProcessIncomingMessageTest method so they run and pass as part of the larger test run that occurs?

    Thanks again.
  2. Chris
    Chris avatar
    21 posts
    Member since:
    Oct 2012

    Posted 06 Jun 2011 Link to this post

    I modified how I am doing things a little bit (realizing that I was most likely architecting things incorrectly).

    I still am needing help however. The issue is I have several test methods that each mock certain NonPublic(private) methods within my class, I then run the public interface method.  When I run these tests individually they work as expected, however when I run them as part of a large test run they fail.  How they fail depends on which test runner I use, If I use the JustCode TestRunner I get the message that items marked mustbecalled were not called, if I use the integrated VSTS test runner I just get an assert failed from the line above it.

    here is some code that I am attempting to run.

    Unit Test Methods
    ///<summary>
           ///  A test for CheckCommError
           ///</summary>
           [TestMethod]
           public void CheckCommErrorWithErrorTest()
           {
               var message = new byte[] { (byte)EagleMessageTypes.SendCommError,BitConverter.GetBytes((ushort)10)[0], BitConverter.GetBytes((ushort)10)[1] };
     
               bool expected = false; // TODO: Initialize to an appropriate value
               bool actual;
               //mock the other members in EagleUtility that are being used...
              var target = new EagleUtility();
               bool called = true;
               Mock.NonPublic.Arrange<bool>(target, "CheckMinimumSize", ArgExpr.IsAny<BasicEagleMessage>(), Arg.AnyInt).IgnoreArguments().DoInstead(
                   (BasicEagleMessage arg1, int arg2) => called = true).Returns(true).MustBeCalled();
               Mock.NonPublic.Arrange<bool>(target, "CheckMessageLength", Arg.AnyInt, ArgExpr.IsAny<BasicEagleMessage>()).IgnoreArguments().DoInstead(
                  (int arg1, BasicEagleMessage arg2) => called = true).Returns(true).MustBeCalled();
               Mock.NonPublic.Arrange<bool>(target, "VerifyCheckSum", ArgExpr.IsAny<byte[]>()).IgnoreArguments().DoInstead(
                  (byte[] arg1) => called = true).Returns(true).MustBeCalled();
               Mock.NonPublic.Arrange<bool>(target, "ValidateLegacyMessageType", ArgExpr.IsAny<BasicEagleMessage>()).IgnoreArguments().DoInstead(
                  (BasicEagleMessage arg1) => called = true).Returns(true).MustBeCalled();
               actual = target.ValidateMessage(message, 3, TowerTypes.Tower4800);
               Assert.AreEqual(expected, actual);
               Mock.Assert(target);
           }
     
           ///<summary>
           ///  A test for CheckMessageLength
           ///</summary>
           [TestMethod]
           public void CheckMessageLengthTest()
           {
               var message = new byte[] { (byte)3, BitConverter.GetBytes((ushort)59006)[0], BitConverter.GetBytes((ushort)59006)[1], 0 };
               var byteCount = 32486;
               bool expected = true;
               bool actual;
               //mock the other members in EagleUtility that are being used...
              var target = new EagleUtility();
               bool called = true;
               Mock.NonPublic.Arrange<bool>(target, "CheckMinimumSize", ArgExpr.IsAny<BasicEagleMessage>(), Arg.AnyInt).IgnoreArguments().DoInstead(
                   (BasicEagleMessage arg1, int arg2) => called = true).Returns(true).MustBeCalled();
               Mock.NonPublic.Arrange<bool>(target, "CheckCommError", ArgExpr.IsAny<BasicEagleMessage>()).IgnoreArguments().DoInstead(
                  (BasicEagleMessage arg2) => called = true).Returns(true).MustBeCalled();
               Mock.NonPublic.Arrange<bool>(target, "VerifyCheckSum", ArgExpr.IsAny<byte[]>()).IgnoreArguments().DoInstead(
                  (byte[] arg1) => called = true).Returns(true).MustBeCalled();
               Mock.NonPublic.Arrange<bool>(target, "ValidateLegacyMessageType", ArgExpr.IsAny<BasicEagleMessage>()).IgnoreArguments().DoInstead(
                  (BasicEagleMessage arg1) => called = true).Returns(true).MustBeCalled();
               actual = target.ValidateMessage(message, byteCount, TowerTypes.Tower4800);
               Assert.AreEqual(expected, actual);
               Mock.Assert(target);
     
           }


    The second test method is what fails.  I do have the following for my ClassInitialize method

    [ClassInitialize()]
           public static void MyClassInitialize(TestContext testContext)
           {
               Mock.Initialize<EagleUtility>();
           }


    Please help.  I have been very impressed with JustMock and I am sure I trying to do something in the wrong way, but I am having troulbe determining the right way.

    Thanks in advance.
  3. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 10 Jun 2011 Link to this post

    Hi Chris,

    In order to test the issue in my local machine, it will be great if you send me a dummy implementation of the EagleUtility class that covers the necessary methods to run those two tests.

    Thanks again for any help regarding the above context.


    Kind Regards,
    Mehfuz
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  4. Muthukumaran
    Muthukumaran avatar
    2 posts
    Member since:
    May 2017

    Posted 16 May Link to this post

    Hi, I am trying to test TcpListener implementation in my project. I am not sure how to partially mock private methods. Are there references that I can look? Here is sample and I am trying to mock GetStream and ReadMessage in different test methods.

    public class SocketListener
        {
            private readonly TcpListener _TcpListener;

            public SocketListener(IPAddress ipAddress, int port)
            {
                // Initialize
                _TcpListener = new TcpListener(ipAddress ?? throw new ArgumentNullException(nameof(ipAddress)), port);
            }

            public SocketListener(TcpListener tcpListener)
            {
                // Initialize
                _TcpListener = tcpListener ?? throw new ArgumentNullException(nameof(tcpListener));
            }
            
            public async Task StartListening()
            {
                try
                {
                    _TcpListener.Start();

                    while (true)
                    {
                        var client = await _TcpListener.AcceptTcpClientAsync().ConfigureAwait(false);   
                        var taskResult = Task.Run(() => ReadMessage(client));
                    }
                }
                catch(ObjectDisposedException)
                {
                    // ignore this error
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

            public void Stop()
            {
                if (_TcpListener != null)
                    _TcpListener.Stop();                        
            }

            private bool ReadMessage(TcpClient client)
            {
                bool result = false;
                try
                {
                    BinaryFormatter deserializer = new BinaryFormatter();
                    dynamic obj = deserializer.Deserialize(GetStream(client));
                    
                    // Process the message
                    // result = ProcessMessage(obj);

                    // close the connection 
                    client.Close();
                }
                catch(Exception ex)
                {
                    string msg = string.Format("ReadMessage failed with an unexpected error. {0}", ex.ToString());
                    _LogProvider.LogError(msg);   
                }

                return result;
            }

            private Stream GetStream(TcpClient tcpClient)
            {
                Stream stream = tcpClient.GetStream() ?? throw new ArgumentNullException();
                return stream;
            }    
    }

    I would appreciate any help. Thanks

  5. Kamen Ivanov
    Admin
    Kamen Ivanov avatar
    65 posts

    Posted 5 days and 22 hours ago Link to this post

    Hello Muthukumaran,

    When you want to mock just a specific methods of a class and the rest to work as the implementation then you have to set the behavior of the mocked object to CallOriginal​ this will make sure that all methods that are not mocked will behave as implemented and only the mocked ones will behave differently - here is our documentation regarding behaviors.

    Here is how it would look like with your example:
    IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
     
    var socketListenerMock = Mock.Create<SocketListener>(Behavior.CallOriginal, ipAddress, 80);

    After you have created the mocked object with the specified behavior the next step is to mock the private
    methods using the NonPublic annotation - here is our documentation regarding mocking private members.

    Mocking GetStream method from your scenario will look like this:
    Mock.NonPublic.Arrange(socketListenerMock, "GetStream").DoInstead(() => mocked code here));


    Regards,
    Kamen Ivanov
    Telerik by Progress
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  6. Muthukumaran
    Muthukumaran avatar
    2 posts
    Member since:
    May 2017

    Posted 5 days and 15 hours ago in reply to Kamen Ivanov Link to this post

    Thank you. Appreciate your help

    It solved my problem

Back to Top