Mock.Create fails on some real objects

8 posts, 1 answers
  1. Justin Dority
    Justin Dority avatar
    4 posts
    Member since:
    Aug 2008

    Posted 14 Jul 2010 Link to this post

    I'm working on a test case against a static method that makes a few calls on an object, and I'm trying to make those calls do nothing.  The issue I'm having is that this:

    TransactionHeaderViewModel

     

    ticket = Mock.Create<TransactionHeaderViewModel>();

     


    fails with the following:
    Test method POSUnitTests.TransactionServiceTest.SaveTransactionTest threw exception:  System.NullReferenceException: Object reference not set to an instance of an object..

    Telerik.JustMock.DynamicProxy.MethodInvocation.Continue() in c:\B\Basilisk\Basilisk CI Build\Sources\CodeBase\Telerik.JustMock\DynamicProxy\MethodInvocation.cs: line 150
    Intercept(IInvocation invocation) in c:\B\Basilisk\Basilisk CI Build\Sources\CodeBase\Telerik.JustMock\Interceptors\ProxyInterceptor.cs: line 35
    TransactionHeaderViewModel_Proxy_a39192a5eca04cbbb79efb55f2387785.GetHashCode(MethodInvocation , Int32 , Boolean )
    TransactionHeaderViewModel_Proxy_a39192a5eca04cbbb79efb55f2387785.GetHashCode()
    get_Instance() in c:\B\Basilisk\Basilisk CI Build\Sources\CodeBase\Telerik.JustMock\MockObject.cs: line 44
    Telerik.JustMock.Mock.Create(Type target, BehaviorMode mode, Object[] args) in c:\B\Basilisk\Basilisk CI Build\Sources\CodeBase\Telerik.JustMock\Mock.cs: line 354
    Telerik.JustMock.Mock.Create(Type target, Object[] args) in c:\B\Basilisk\Basilisk CI Build\Sources\CodeBase\Telerik.JustMock\Mock.cs: line 339
    Telerik.JustMock.Mock.Create[T]() in c:\B\Basilisk\Basilisk CI Build\Sources\CodeBase\Telerik.JustMock\Mock.cs: line 328
    POSUnitTests.TransactionServiceTest.SaveTransactionTest() in c:\tfs\Point of Sale\POSApp\Main\Source\POSUnitTests\TransactionServiceTest.cs: line 151


    If I just do a TransactionHeaderViewModel ticket = new TransactionHeaderViewModel(); instead, then the calls to Mock.Arrange(() => ticket.SetLineNumbers()).DoNothing(); don't actually work, when debugging the test case you can see that the actual code is called.  I also tried making SetLineNumbers() a virtual, but that caused the "Opps" error.

    I thought that it was having an issue with what the constructor was doing, so I commented out everything in the constructor, but still get the same error (in fact, the error above is from that simplified case).

    Any thoughts, or is this something that's already fixed in the current builds?  I'm on the 528.5 beta release.


    Thanks,
         Justin
  2. Chris
    Admin
    Chris avatar
    221 posts

    Posted 14 Jul 2010 Link to this post

    Hello Justin,

    The official Q2 2010 version has just been released. Could you please download it and try this with the latest version?

    Regards,
    Chris
    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
  3. DevCraft R3 2016 release webinar banner
  4. Justin Dority
    Justin Dority avatar
    4 posts
    Member since:
    Aug 2008

    Posted 14 Jul 2010 Link to this post

    Thanks, that seems to work now, but I now have another issue.  I'm setting up a static property and method to return specific values like this:

     

    Mock.Arrange(() => UserService.Username).Returns("testUser");

     

     

    Mock.Arrange(() => UserService.GetLoggedInUser()).Returns(new BBA.POS.Data.Settings.POSUser() { UserId = "testUser" });

     

     

    Mock.Arrange(() => ConfigurationService.GetConfiguration()).Returns(new BBA.POS.Data.Settings.TerminalSettings() { TerminalNumber = 5 });

     

     

    These used to work in the beta version, but now only the UserService.Username property returns what was arranged.  The two static methods both run the original version (and consequently return null).  Did something change so I'm missing a step now?

    Thanks,

         Justin

  5. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 15 Jul 2010 Link to this post

    Hi Justin,
    There was a little issue regarding type loading that I fixed just after the release and will be available in the next build. To reproduce the issue, I wrote a similar test from that you have shown here. Let me know, if it correctly covers your case so that we are on the right page.

    [TestMethod]
    public void ShouldAssertMultipleStaticSetups()
    {
        Mock.Arrange(() => UserServices.UserName).Returns("Justin");
        Mock.Arrange(() => UserServices.GetLogginUser()).Returns(new User());
        Mock.Arrange(() => UserServices.GetConfiguration()).Returns(new Configuration());
        Assert.Equal("Justin", UserServices.UserName);
        Assert.NotNull(UserServices.GetLogginUser());
        Assert.NotNull(UserServices.GetConfiguration());
    }
    public class UserServices
    {
        public static string UserName { get; set; }
        public static User GetLogginUser()
        {
            return null;
        }
        public static Configuration GetConfiguration()
        {
            return null;
        }
    }
    public class User
    {
    }
    public class Configuration
    {
    }

    Finally, to avoid the issue with current build, I would suggest splitting up the test into three test methods that deals with those calls separetly.

    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
  6. Justin Dority
    Justin Dority avatar
    4 posts
    Member since:
    Aug 2008

    Posted 15 Jul 2010 Link to this post

    Thanks, I'll try the next build when I get a chance.  The static property (UserServices.UserName in that example) works, but the static methods don't.  The test case in question is one for another static method that uses all of these, the full code of the test method is:

    [TestMethod()]
    public void SaveTransactionTest()
    {
        TransactionHeaderViewModel ticket = Mock.Create<TransactionHeaderViewModel>();
        bool recalculate = false;
        Random r = new Random();
        int resNumber = r.Next(9999);
        Mock.Arrange(() => UserService.Username).Returns("testUser");
        Mock.Arrange(() => UserService.GetLoggedInUser()).Returns(new BBA.POS.Data.Settings.POSUser() { UserId = "testUser" });
        Mock.Arrange(() => ConfigurationService.GetConfiguration()).Returns(new BBA.POS.Data.Settings.TerminalSettings() { TerminalNumber = 5 });
        // Now set up the transaction save calls
        Mock.Arrange(() => TransactionService.RecalculateTicket(Arg.IsAny<TransactionHeaderViewModel>())).IgnoreArguments().DoNothing();
        Mock.Arrange(() => ticket.SetLineNumbers()).DoNothing();
        Mock.Arrange(() => ticket.SetPaidAmount()).DoNothing();
        Mock.Arrange(() => ticket.SaveTicket()).DoNothing();
        Mock.Arrange(() => TransactionService.GetReservationNumber(Arg.IsAny<string>())).IgnoreArguments().Returns(resNumber);
        // Check that RecalculateTicket was not called, but the others were, and operatorId is still null
        TransactionService.SaveTransaction(ticket, recalculate);
        Mock.Assert(() => TransactionService.RecalculateTicket(Arg.IsAny<TransactionHeaderViewModel>()), Occurs.Never());
        Mock.Assert(() => TransactionService.GetReservationNumber(Arg.IsAny<string>()), Occurs.Once());
        Mock.Assert(() => ticket.SetLineNumbers(), Occurs.Once());
        Mock.Assert(() => ticket.SetPaidAmount(), Occurs.Once());
        Mock.Assert(() => ticket.SaveTicket(), Occurs.Once());
        Assert.Equals(ticket.ReservationNumber, resNumber);
        Assert.IsTrue(string.IsNullOrEmpty(ticket.OperatorId));
    }

    The problem is that it's blowing up with a NullReferenceException due to the UserService.GetLoggedInUser() call returning null inside the TransactionService.SaveTransaction call.

    If I've missed something simple in there, let me know, otherwise, I'll wait for the next build to be released.


    Thanks,

         Justin
  7. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 16 Jul 2010 Link to this post

    Hi Justin,

    Thanks for the test method. Looking at your test closely, I found few issues and  wrote the test in the following way :

    TransactionHeaderViewModel ticket = Mock.Create<TransactionHeaderViewModel>(Behavior.CallOriginal);
    bool recalculate = false;
    Random r = new Random();
    int resNumber = r.Next(9999);
    Mock.Arrange(() => UserService.Username).Returns("testUser");
    Mock.Arrange(() => UserService.GetLoggedInUser()).Returns(new User());
    Mock.Arrange(() => ConfigurationService.GetConfiguration()).Returns(new Configuration());
    // Now set up the transaction save calls 
    Mock.Arrange(() => TransactionService.RecalculateTicket(null)).IgnoreArguments().DoNothing();
    Mock.Arrange(() => ticket.SetLineNumbers()).DoNothing();
    Mock.Arrange(() => ticket.SetPaidAmount()).DoNothing();
    Mock.Arrange(() => ticket.SaveTicket()).DoNothing();
    Mock.Arrange(() => TransactionService.GetReservationNumber("")).IgnoreArguments().Returns(resNumber);
    // Check that RecalculateTicket was not called, but the others were, and operatorId is still null 
    TransactionService.SaveTransaction(ticket, recalculate);
    Mock.Assert(() => TransactionService.RecalculateTicket(Arg.IsAny<TransactionHeaderViewModel>()), Occurs.Never());
    Mock.Assert(() => TransactionService.GetReservationNumber(Arg.IsAny<string>()), Occurs.Once());
    Mock.Assert(() => ticket.SetLineNumbers(), Occurs.Once());
    Mock.Assert(() => ticket.SetPaidAmount(), Occurs.Once());
    Mock.Assert(() => ticket.SaveTicket(), Occurs.Once());
    Assert.AreEqual(ticket.ReservationNumber, resNumber);
    Assert.IsTrue(string.IsNullOrEmpty(ticket.OperatorId));

    Instead of :
    TransactionHeaderViewModel ticket = Mock.Create<TransactionHeaderViewModel>();

    I added this :
    TransactionHeaderViewModel ticket = Mock.Create<TransactionHeaderViewModel>(Behavior.CallOriginal);

    Note that i added Behavior.CallOriginal that means by default it will invoke the original method unless otherwise specified using Mock.Arrange as you have this lines at the end:


    Assert.AreEqual(ticket.ReservationNumber, resNumber);
    Assert.IsTrue(string.IsNullOrEmpty(ticket.OperatorId));


    The properties ReservationNumber and OperationId and is set directly in SaveTicket function without any setup and finally, you asserted the values as if in the original object.  For other other cases,  you have Mock.Arrange so better to put Behavior.CallOriginal.

    Secondly, I modified :

    Mock.Arrange(() => TransactionService.RecalculateTicket(Arg.IsAny<TransactionHeaderViewModel>())).IgnoreArguments().DoNothing(); 
      
    // And
    Mock.Arrange(() => TransactionService.GetReservationNumber(Arg.IsAny<string>())).IgnoreArguments().Returns(resNumber);


    To more simpler :

    Mock.Arrange(() => TransactionService.RecalculateTicket(null)).IgnoreArguments().DoNothing(); 
      
    // And
    Mock.Arrange(() => TransactionService.GetReservationNumber("")).IgnoreArguments().Returns(resNumber);


    As, you are using IgnoreArguments, you don't need the extra Arg.IsAny as you are specifying to ignore the arguments anyway.

    Finally, I reproduced the test and ran it in my local machine with the trial build from justmock download page and i found the test is passing. Make sure that you throw proper exception for UserService.Username and your elevated tests in the supplied examples passing.

    I am also attaching the file, let me know if that passes for you and feel to modify the class structure and send me back in case of failure.

    Regards,
    Mehfuz


    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
  8. Justin Dority
    Justin Dority avatar
    4 posts
    Member since:
    Aug 2008

    Posted 16 Jul 2010 Link to this post

    Thanks Mehfuz, I think we're on the right track.  The solution you attached works fine for me in both VS 2010 and VS 2008, but the changes to my real project didn't resolve the issue, one of the static methods is still returning null instead of the Arrange() value.  I changed the project around a bit to move the data and services to separate classes as they are in my real project.  When I moved the data classes, it still worked fine, but after I moved the service classes, the test failed because the ConfigurationService.GetConfiguration() call returned null (the real code result) instead of a new Configuration (the Arrange() result).

    I have attached that solution to support ticket #328879.
  9. Answer
    Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 19 Jul 2010 Link to this post


    Hi Justin,

    There is an answer posted to the ticket # 328879 that deals with this issue, please check it out.

    Regards,
    Mehfuz


    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
Back to Top
DevCraft R3 2016 release webinar banner