Mockito: how to test that a constructor was called?
Solution 1
This can't be done with Mockito, since the object being created is not a mocked object. This also means that you won't be able to verify anything on that new object either.
I've worked around this scenario in the past by using a Factory
to create the object rather than newing it up. You're then able to mock the Factory
to return the object required for your test.
Whether you're happy changing your design to suit your tests is up to you!
Solution 2
You can do it with Mockito and PowerMockito.
Say you have ClassUnderTest with a constructor
public class ClassUnderTest {
String name;
boolean condition;
public ClassUnderTest(String name, boolean condition) {
this.name = name;
this.condition = condition;
init();
}
...
}
And another class that calls that constructor
public class MyClass {
public MyClass() { }
public void createCUTInstance() {
// ...
ClassUnderTest cut = new ClassUnderTest("abc", true);
// ...
}
...
}
At the Test class we could...
(1) use PowerMockRunner and cite both target classes above in the PrepareForTest annotation:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ ClassUnderTest.class, MyClass.class })
public class TestClass {
(2) intercept the constructor to return a mock object:
@Before
public void setup() {
ClassUnderTest cutMock = Mockito.mock(ClassUnderTest.class);
PowerMockito.whenNew(ClassUnderTest.class)
.withArguments(Matchers.anyString(), Matchers.anyBoolean())
.thenReturn(cutMock);
}
(3) validate the constructor call:
@Test
public void testMethod() {
// prepare
MyClasss myClass = new MyClass();
// execute
myClass.createCUTInstance();
// checks if the constructor has been called once and with the expected argument values:
String name = "abc";
String condition = true;
PowerMockito.verifyNew(ClassUnderTest.class).withArguments(name, condition);
}
Solution 3
With Mockito can do something
try (MockedConstruction<MyClass> myclass = Mockito.mockConstruction(
MyClass.class)) {
........
Assert.assertEquals(1, myClass.constructed().size());
}
Solution 4
verify()
method waits for mocked object(already created object). And constructor
can not be called on created object
.
Solution 5
This is not possible with Mockito and sounds like a bad design.
You can use a factory and pass it to the object under test. After that you can easily mock the factory and verify that its create method was called.
By directly creating objects in your code you are making a hard dependency to concrete implementations, which makes the code harder and sometimes impossible to unit test. This is addressed with Dependency Injection (DI) and Inversion of Control (IoC).
Related videos on Youtube
java123999
Updated on February 16, 2022Comments
-
java123999 over 2 years
I am using Mockito to test methods within my Java application.
How can I test that a constructor was called once?
I am trying to do a verification similar to this:
verify(myClass, times(1)).doSomething(anotherObject);
But I can't verify that the constructor was called as it doesn't have a method similar to e.g.
doSomething()
.-
Marcus Müller almost 8 yearsUm, you can't get an Object if you don't call it's constructor; that's a language feature.
-
java123999 almost 8 yearsplease explain what you mean
-
Rogério almost 8 yearsYou should describe what it is that you're actually trying to test, that made you think you needed to mock a constructor. I wouldn't be surprised if there is no real need for it.
-
-
Wim Coenen almost 8 yearsOP isn't asking how to verify that the constructor works, but how to verify that some other code indeed calls the constructor.
-
java123999 almost 8 yearsThis seems the best fix. Ill look into using a Factory class in future to solve this
-
Rogério almost 8 yearsIntroducing a factory to work around a limitation in the mocking library... that's obviously not a good solution. Instead, I would suggest to avoid the supposed need to mock the class being instantiated from the SUT. Usually, a better test with no mocking is possible.
-
Willie Z over 6 yearsI think the sequence of the last two lines in your testMethod() should swap. like this: new ClassUnderTest(name, condition); PowerMockito.verifyNew(ClassUnderTest.class);
-
Jose Tepedino over 6 years@WillieZ, thank you so much for calling my attention about this test method! In truth, that previous last command was not really needed. The original idea was to test the constructor call with certain specific argument values, in a method under test called in the execute phase. I've just rewritten the code to express my original intention. I hope it is clearer now.
-
Riding Cave over 3 yearsverify(MyClass.class,times(1)).newInstance();
-
Dustin over 2 yearsThis does not work. The first argument passed to
verify()
must be a mock.