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());
}
}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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());
}
}
I've also tried using private String name = ""; in the definition section with the same result.
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.
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
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
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).
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.