This is a migrated thread and some comments may be shown as answers.

Partial Mocking of Private Method not working in large test run

5 Answers 176 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Chris
Top achievements
Rank 1
Chris asked on 03 Jun 2011, 02:20 PM
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.

5 Answers, 1 is accepted

Sort by
0
Chris
Top achievements
Rank 1
answered on 06 Jun 2011, 02:38 PM
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.
0
Ricky
Telerik team
answered on 10 Jun 2011, 10:39 AM
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
0
Muthukumaran
Top achievements
Rank 1
answered on 16 May 2017, 03:16 PM

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

0
Kamen Ivanov
Telerik team
answered on 19 May 2017, 07:34 AM
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
0
Muthukumaran
Top achievements
Rank 1
answered on 19 May 2017, 02:03 PM

Thank you. Appreciate your help

It solved my problem

Tags
General Discussions
Asked by
Chris
Top achievements
Rank 1
Answers by
Chris
Top achievements
Rank 1
Ricky
Telerik team
Muthukumaran
Top achievements
Rank 1
Kamen Ivanov
Telerik team
Share this question
or