Menu

PartialMock objects not properly constructed

Users
2009-04-23
2013-05-28
  • James Davis

    James Davis - 2009-04-23

    I'm having some issues using PartialMock and I'm not quite sure what's going on here.  It almost appears that when unitils creates the mock, it doesn't call the constructors.  As a result, some of the methods in the actual implementation are failing.

    Example:

    public abstract class MockMe
    {
        private String name;

        public MockMe()
        {
            name = "";
        }

        public int getNameLength()
        {
            return name.length();
        }
    }

    When I create the follwing test, I get an NPE on (return name.length()) because name is null. 
    public class TestMockMe extends UnitilsJUnit4
    {
        private PartialMock<MockMe> mock1;

        @Test
        public void mockTest()
        {
            assertEquals("oops.", 0, mock1.getMock().getNameLength());
        }
    }

     
    • James Davis

      James Davis - 2009-04-23

      I've also tried using private String name = ""; in the definition section with the same result.

       
    • James Davis

      James Davis - 2009-04-23

      I have also tried the following:

      public abstract class MockMe
      {
      private String name = "";

      public MockMe()
      {
      }

      public int getNameLength()
      {
      return name.length();
      }
      }

      with the same result.

       
      • Tim Ducheyne

        Tim Ducheyne - 2009-04-24

        Hi James,

        I've created a JIRA issue for it:

        http://jira.unitils.org/browse/UNI-124

        Shouldn't we make the behavior configurable? I suppose there are cases where you don't want the constructor to be called.

        Thanks for reporting this.

        Gtz,
        Tim

         
        • Jeff Jones

          Jeff Jones - 2009-04-24

          I've noticed the same problem.  As a workaround, I've used this:

              @InjectInto(property="getMock().myHoo", target="duh") public Hoo youHoo = new Hoo(-42);
              @TestedObject public PartialMock<NLDummyObjectForUnitilsUnitTest> duh;

              @Test
              public void testInjectionIntoPartialMockedObject() throws Exception
              {
                  Assert.assertEquals(-42, duh.getMock().getMyHoo().get());
              }

          I started looking into fixing this, but I haven't figured out how to do it with objenesis.  I also found a blog post somewhere that said something like "objenesis seems to be specifically designed to avoid calling the constructor." 

          That's as far as I've gotten at this point.

          Thanks.

             - Jeff

           
    • James Davis

      James Davis - 2009-04-24

      Thanks Tim.

      I think it might be useful to have some way to configure calls to constructors, maybe with an annotation of IgnoreConstructorCalls.  However, if the variable is defined/initialized in the class definition, it should always be initialized (not sure if that requires a constructor call though).

       
    • James Davis

      James Davis - 2009-04-24

      Looking at the Objenesis docs, there are two strategies to instantiate objects.

      There are many different strategies that Objenesis uses for instantiating objects based on the JVM vendor, JVM version, SecurityManager and type of class being instantiated.

      We have defined that two different kinds of instantiation are required:

          * Stardard - No constructor will be called
          * Serializable compliant - Acts like an object instantiated by java standard serialization. It means that the constructor of the first non-serializable parent class will be called. However, readResolve is not called and we never check if the object is serializable.

      So, having an attribute that determines if it uses the standard or Serializable compliant might fix this.

       

Anonymous
Anonymous

Add attachments
Cancel