Mocking static method throws exception

13 posts, 0 answers
  1. Ben
    Ben avatar
    8 posts
    Member since:
    May 2013

    Posted 14 May 2013 Link to this post

    Hi,

    I'm currently using the trial of JustMock to write some demo tests for our code. We are using Sitecore CMS and it uses a lot of static properties.

    I have this very simple class I want to use for some testing and I have mocked the static property Item on the Context like so:

    public class when_accessing_the_context_item_it_should_return_the_name
        {
            static string _result;

            Establish context = () =>
                {
                    Mock.SetupStatic(typeof(Sitecore.Context), StaticConstructor.Mocked);

                    var mockItem = Mock.Create<Item>();
                    Mock.Arrange(() => mockItem.Name).Returns("thename");
                    Mock.Arrange(() => Sitecore.Context.Item).Returns(mockItem);
                };

            Because of = () =>
            {
                _result = new MyRendering().Render();
            };

            It should_return_the_name_of_the_item = () =>
            {
                _result.ShouldEqual("thename");
            };


        }

        public class MyRendering
        {
            public string Render()
            {
                return Sitecore.Context.Item.Name;
            }
        }

    However when running the test I get an exception:

    System.ArgumentNullException: Value cannot be null.
    Parameter name: itemID
       at Telerik.JustMock.DynamicProxy.ProxyFactory.CreateInstance(Type type, Object[] extArgs)
       at Telerik.JustMock.DynamicProxy.ProxyFactory.Create()
       at Telerik.JustMock.DynamicProxy.Fluent.FluentProxy.NewInstance()
       at Telerik.JustMock.DynamicProxy.Proxy.Create(Type type, Action`1 action)
       at Telerik.JustMock.MockManager.CreateProxy(Type targetType, Container container)
       at Telerik.JustMock.MockManager.CreateMock(Container& container)
       at Telerik.JustMock.MockManager.SetupMock(Behavior behavior, Boolean isStaticType)
       at Telerik.JustMock.MockManager.CreateInstance()
       at Telerik.JustMock.Mock.Create(Type target, Behavior behavior, Object[] args)
       at Telerik.JustMock.Mock.Create(Type target, Object[] args)
       at Telerik.JustMock.Mock.Create[T]()
       at Demo.Tests.When_accessing_the_context_item_it_should_return_the_name.<.ctor>b__0() in 

    Why am I seeing this exception, am I doing something wrong?
  2. Ben
    Ben avatar
    8 posts
    Member since:
    May 2013

    Posted 14 May 2013 Link to this post

    I figured out what the problem was, I'm now using:

    var mockitem = Mock.Create<Item>(Constructor.Mocked);
                    
    To prevent the constructor from running. However when I setup the static property now:

    Mock.SetupStatic(typeof(Sitecore.Context), StaticConstructor.Mocked);

                    var mockitem = Mock.Create<Item>(Constructor.Mocked);
                    Mock.Arrange(() => mockitem.Name).Returns("thename");
                    Mock.Arrange(() => Sitecore.Context.Item).Returns(mockitem);

    I'm now getting a NullReferenceException:

    System.NullReferenceException: Object reference not set to an instance of an object.
       at RefreshLayout.UI.Tests.MyRendering.Render() in C:\Users\demo\Desktop\JustMockDemo\Demo.Tests\Class1.cs:line 90#0
       at RefreshLayout.UI.Tests.When_acessing_the_context_item_it_should_return_the_name.<.ctor>b__1() in C:\Users\demo\Desktop\JustMockDemo\Demo.Tests\Class1.cs:line 75#1

  3. DevCraft R3 2016 release webinar banner
  4. Ben
    Ben avatar
    8 posts
    Member since:
    May 2013

    Posted 14 May 2013 Link to this post

    This is a bit strange. When I debug the test inspecting properties along the way everything seems fine and the test passed. Without inspecting the properties or just running it normally the test fails.....
  5. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 16 May 2013 Link to this post

    Hello Just,

    Thank you for contacting Telerik support.

    Unfortunately, I was not able to reproduce such behavior of JustMock.

    To further investigate the issue, I will need a sample project (containing the system under test, in your case this will be the Sitecore.Context and the Item class). If doable, please isolate this current test method and send it over. Then I will be able to provide solution or at least a workaround to that matter.

    Thank you for the cooperation in advance.

    Greetings,
    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.
  6. Ben
    Ben avatar
    8 posts
    Member since:
    May 2013

    Posted 16 May 2013 Link to this post

    Here is a demo solution. Download.

    I'm using NCrunch runner but also tried the ReSharper runner both fail. To run in ReSharper you need to install a runner package from the Machine.Specifications package.

    Thanks.
  7. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 17 May 2013 Link to this post

    Hello Just,

    Thanks for the detailed project. I have attached its reworked version with the test passing.

    What I did:
    1. First, I noticed you were referring "Telerik.JustMock.VisualBasic" inside your repro project. Since it is a C# project, you would need to use the "Telerik.JustMock" assembly. I changed that.
    2. Next, I started refactoring your test. You were trying to mock the Item class along with its constructor (Mock.Create<Item>(Constructor.Mocked). Here, I should note that, when you set Constructor.Mocked for a certain mock object, you explicitly say there won`t be any "constructions" in that object. This means, the constructor will be rewritten to a default constructor and further the properties won`t be initialized, they will be nulls. Here comes the NullReferenceException. To escape it, I had to isolate the Item class from its dependencies passed in the constructor. To achieve this, I mocked them with Constructor.Mocked, as now I didn`t needed any of their properties initialized. I needed only stubs. Finally, I passed them as arguments to the "mockitem".
    3. Also, I removed the Constructor.Mocked in "Mock.SetupStatic(typeof(Sitecore.Context))", as it was not needed. The rest of your test logic was correct.
    4. Just to add that, I had to add a reference to Lucente.Net version: 2.3.1.3, as it was missing.

    I hope this helps. Please, contact us again if you need more help.

    Greetings,
    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.
  8. Ben
    Ben avatar
    8 posts
    Member since:
    May 2013

    Posted 17 May 2013 Link to this post

    Thanks, I'll check it out. Not sure how the VB reference made it in there but thanks for spotting it.
  9. Ben
    Ben avatar
    8 posts
    Member since:
    May 2013

    Posted 17 May 2013 Link to this post

    Can you explain why when debugging the test I set up all the properties seem to be set correctly and even the name is being returned properly? I've debugged it several times and all the values are being returned correctly but it still fails with the NullReference.

    Also is it possible to have the constructor parameters for item automatically mocked so I don't have to do that manually?


    In addition to the questions above I have added some more simple tests to my project which also give me errors. I have written two helper methods:

    public class Helpers
        {
            public static Item CreateMockItem()
            {
                var mockId = Mock.Create<Sitecore.Data.ID>(Constructor.Mocked);
                var mockItemData = Mock.Create<Sitecore.Data.ItemData>(Constructor.Mocked);
                var mockDatabase = Mock.Create<Sitecore.Data.Database>(Constructor.Mocked);
                var mockItem = Mock.Create<Item>(mockId, mockItemData, mockDatabase);

                return mockItem;
            }

            public static Field CreateMockField(string returnValue, Item ownerItem)
            {
                var mockId = Mock.Create<Sitecore.Data.ID>(Constructor.Mocked);
                var mockField = Mock.Create<Field>(mockId, ownerItem);
                mockField.SetValue(returnValue, true);

                return mockField;
            }
        }

    Now I would like to test a rendering like so:

    [Subject(typeof(TafePathwaysRenderer))]
        public class when_a_valid_configuration_is_present
        {
            private static TafePathwaysRenderer _renderer;
            private static string _result;

            Establish context = () =>
                {
                    _renderer = Mock.Create<TafePathwaysRenderer>(Behavor.CallOriginal);
                    var mockItem = Helpers.CreateMockItem();
                    Mock.Arrange(() => mockItem.Fields["heading"]).Returns(Helpers.CreateMockField("Heading field value", mockItem));
                    Mock.NonPublic.Arrange<Item>(_renderer, "Configuration").Returns(mockItem);
                };

            Because of = () =>
            {
                _result = _renderer.RenderAsText();
            };

            It should_render_a_heading_containing_the_heading_field_value = () =>
            {
                _result.ShouldContain("<h2 class=\"page-title\">Heading field value</h2>");
            };
        }

    This gives me an error:
    System.NullReferenceException: Object reference not set to an instance of an object.
       at Telerik.JustMock.DynamicProxy.MethodInvocation.Continue()
       at Telerik.JustMock.Interceptors.ProxyInterceptor.Continue(IInvocation invocation, Object[] args)
       at Telerik.JustMock.Interceptors.ProxyInterceptor.Intercept(IInvocation invocation)
       at TafePathwaysRendererProxy\.cc8854bb1a1c418f9a015d20c0d1e41b._RenderAsText(MethodInvocation , Int32 , Boolean )
       at TafePathwaysRendererProxy\.cc8854bb1a1c418f9a015d20c0d1e41b.RenderAsText()
       at Layout.UI.Tests.when_a_valid_configuration_is_present.<.ctor>b__1() in repo\Layout.UI.Tests\Class1.cs:line 69#0

    Thanks for your help.
  10. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 22 May 2013 Link to this post

    Hello Just,

    Investigating your test I noticed the Sitecore.Context.Item is null while debugging. This is due to the using of:
    Mock.SetupStatic(typeof(Sitecore.Context), StaticConstructor.Mocked);
    Even arranged to return "mockitem" the Sitecore.Context.Item will throw NullReferenceException if not constructed, as its type is not specified. If you remove the StaticConstructor.Mocked the SiteCore.Context class will be initialized with the original implementation of its members and methods. However, if for any reason you want to keep the StaticConstructor.Mocked you will need to initialize the "Item" property manually, like this: Sitecore.Context.Item = mockitem; Having this, you could further remove this line from your test, as it won`t be needed:
    Mock.Arrange(() => Sitecore.Context.Item).Returns(mockitem);

    About your second question, there is such functionality in JustMock. It is called Automocking. You could read a lot more about it here. However, as the automocking is still a work in progress, if you try to automock the "Item" class it will throw an exception. This is due to the fact, the JustMock automocking goes recursively and mocks all of the dependencies passed through the constructor of the MockingContainer class. This means, it will try to mock:
    • Sitecore.Data.ID
    • Sitecore.Data.ItemData
    • Sitecore.Data.Database
    Then it will do the same automocking for the above classes (it is a recursive process). However, as you can check, the "ID" and the "Database" classes are having arguments of type string passed in their constructors. Here JustMock will throw an exception due to not being able to mock a type of string.

    About your tests, could you please wrap them once again into a compiling project, reproducing the issues? If this is not doable, I will at least need the "TafePathwaysRenderer" class so I can reproduce them on my side.

    I hope this helps.

    Regards,
    Kaloyan
    Telerik
    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.
  11. Ben
    Ben avatar
    8 posts
    Member since:
    May 2013

    Posted 23 May 2013 Link to this post

    I've emailed the solution.
  12. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 24 May 2013 Link to this post

    Hi Ben,

    Thank you for the sample project.

    I tested it with the latest JustMock official release (JustMock 2013 Q2 Internal Build 2013.2.522) and everything passed. I recommend updating to the above JustMock version as there are a lot of improvements and bug fixes in it. Release notes could be found here.

    Please, let me know if this helps.

    Regards,
    Kaloyan
    Telerik
    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.
  13. Ben
    Ben avatar
    8 posts
    Member since:
    May 2013

    Posted 26 May 2013 Link to this post

    Hi Kaloyan 

    I have updated my JustMock installation but I still get failing tests(both ReSharper test runner and NCrunch). For some testing purposes I have changed the setttings of NCrunch to run each test in a new process and suddenly the test pass. When I change to parallel execution they start failing again. 

    I assume this is related to mocking the GetItem() method returning a different item depending on the test which seems to interfere with other tests run in parallel. Is there any way I can isolate mocked items so they don't interfere with other tests being run?

    Thanks.
  14. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 28 May 2013 Link to this post

    Hi Ben,

    Thanks for the feedback.

    You are correct, the tests are sometimes failing with NCrunch when executed in parallel. It appears there is a racing issue that leads to this. However, we will further investigate it and provide a solution as soon as possible.

    Meanwhile, I could only suggest you to execute your tests in a single process.

    Further, I am glad to say that we have released a new internal build of JustMock Q2 2013. We have improved the compatibility with NCrunch in it, so feel free to try it out.

    Note that, to use the JustMock profiler with NCrunch you will need to:
    1. Openthe NCrunch configuration window for your test assembly. You could right click the test assembly from the NCrunch Tests window and select Configure selected component.
    2. Then, navigate to Test Settings and point the exact location of the JustMockRunner (by default: C:\Program Files (x86)\Telerik\JustMock\Libraries\JustMockRunner.exe) for "Proxy process file path", as shown in the attached screenshot.

    I hope this helps.

    Regards,
    Kaloyan
    Telerik
    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