Mock constructor with mockito - java

I want to mock a constructor into method.
public String generaID() {
GeneraIDParaEntidadCliente aux = new GeneraIDParaEntidadCliente(nombre, registro);
entidad.setID(aux.generaID);
}
In my test I want do something like this :
when(new GeneraIDParaEntidadCliente(anyString(), any(Entidad.class)).thenReturn(generaIdMock)
but give me this error org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Any idea why?

UPDATE: since since version 3.5.0, Mockito can do this without PowerMockito.
You can use PowerMock to mock constructors.
If you can't use PowerMock for some reason, the most workable solution is to inject a factory to whatever class contains this method. You would then use the factory to create your GeneraIDParaEntidadCliente object and mock the factory.

There are a couple of ways of doing this, described in my article on the Mockito wiki

Copying answer from duplicate:
Mockito can now mock constructors (since version 3.5.0) https://javadoc.io/static/org.mockito/mockito-core/3.5.13/org/mockito/Mockito.html#mocked_construction
try (MockedConstruction mocked = mockConstruction(Foo.class)) {
Foo foo = new Foo();
when(foo.method()).thenReturn("bar");
assertEquals("bar", foo.method());
verify(foo).method();
}

you can send mocked objects as paramemters to your class constructor, form example:
// define you object
public MainClassObj instanceClass;
// mock input parameter
MYClassObj mockedObj = Mockito.mock(MYClassObj.class);
// call construvtor with mocked parameter
instanceClass = new instanceClass(mockedObj);

Related

Using PowerMockito and Mockito to test call to other artifact's method

I am sure this is quite a common question now, but I really can't get away with this issue I am having on mocking private method which internally calls another method and returns a collection.
Class that I am testing has a public method which calls private method to get Collection object. I use PowerMock to create a spy of private method.
public void method1(String s)
{
Collection<Object> list = invokePrivate()
}
private Collection<Object> invokePrivate()
{
Wrapper wrapperObj = Factory.getInstance.getWrapper();
Collection<Object> list = wrapperObj.callWrapperMethod(); // This always calls into real method, instead of mocked version.
return list;
}
Test Class-:
So In order to test public method "method1" I create a spy using PowerMockito to spy over private method and return a demo list.
MainClass obj = new MainClass();
MainClass spy = PowerMockito.spy(obj);
PowerMockito.when(spy, method(MainClass.class, "inokePrivate"))
.thenReturn(list); // demo list which exists as a test class member.
Above calls into private method which in turns tries to call wrapperObj.callWrapperMethod() which resides in a different artifact and breaks there because some implementation it doesn't find there.
So I try to mock wrapperObj.callWrapperMethod.
WrapperClass wr = new WrapperClass();
WrapperClass spy1 = PowerMockito.spy(wr);
when(spy1.callWrapperMethod()).thenReturn(list) // demo list which exists as a test class member.
Above mocking again calls into actual implementation of callWrapperMethod() and breaks in there.
How can I prevent calling into actual implementation of wrapper method?
Few of the answers that helped me-:
Mockito:How to mock method called inside another method
Testing Private method using mockito
[UPDATE] -: as suggested as I did following-:
PowerMockito.doReturn(list).when(spy1).callWrapperMethod(); // This returns me demo list successfully.
But now when I call private method from PowerMockito control goes into invokePrivate method and again tries to call original callWrapperMethod instead of return list from spy version.
I suggest to not do it this way. Your private method should not retrieve the singleton factory object using a static method.
Static stuff breaks "easy" mocking; forces you to use "power" mocking; and thereby, creates more problems than it solves.
Change your code to use dependency injection. Do something like this:
class YourClass {
private final Factory factory;
public YourClass() {
this(Factory.getInstance(); }
YourClass(Factory theFactory) {
this.factory = theFactory;
...
This will allow you to use the second constructor in your unit test; to provide a (easily mocked) factory object for your class. Thereby you eliminate the whole need for PowerMock.
Long story short - when code is hard to test; change the code; and not the test. As a side effect, you are improving the quality of your code - because you loose the hard dependency on that singleton object.
And just to be complete: I also recommend to avoid "breaking" the Law of Demeter ( http://en.wikipedia.org/wiki/Law_of_Demeter ): if your class needs the wrapper; then it should hold a wrapper object; if it needs that factory; then it should hold a factory object. But you should not hold one object ... to retrieve another object from there, to run something on that second object. As you see - doing so leads exactly to the sort of problem that you are facing.

unable to mock generic object creation

I want to mock dao creation for following method.
private ReturnType createTenant(){
TenantDto tenantDto = new TenantDto();
TenantGroupDto tenantUserGroupDto = new TenantGroupDto(DEFAULT_USER_GROUP_NAME,Type.HUMAN,DEFAULT_USER_GROUP_DESCR, true);
TenantGroupDto tenantDeviceGroupDto = new TenantGroupDto(DEFAULT_DEVICE_GROUP_NAME,Type.DEVICE,DEFAULT_DEVICE_GROUP_DESCR, true);
Set<TenantGroupDto> tenantGroups = new HashSet<TenantGroupDto>();
tenantGroups.add(tenantUserGroupDto);
tenantGroups.add(tenantDeviceGroupDto);
tenantDto.setTenantGroup(tenantGroups);
tenantDto = tenantDao.create(tenantDto);
return someOtherOperation(tenantDto);
}
I'm able to mock rest of the things however. I'm unable to mock generic creation.
i.e.
Set<TenantGroupDto> tenantGroups = new HashSet<TenantGroupDto>();
It is required to be mocked since tenantGroups is parameter to
tenantDao.create(tenantDto);
Most of the links/questions I search about are when the generic object gets returned from some method. I couldn't find any solution to creation of generic object. Any help is appreciated.
Thx in Advance.
This is how to create a mock of a generic class.
#Mock
Set<TenantGroupDto> tenantGroups
#Before
public void init(){
MockitoAnnotations.initMocks(this);
}
#Test
public void myTest(){
when(tenantGroups....
}
Mockito (alone) can't truly mock the instantiation of objects, Generics or otherwise (although you can get close).
This is a classic reason why people use the Factory pattern, allowing pluggable factories to allow differing types of objects decided at runtime, or to allow neat, encapsulated testing with mocks / stubs like in this situation.
As for the collections (e.g. HashSet), there is very little reason to test them; just make sure your (domain) objects are fully tested, and you should be covering the right code in your tests.

how to test methods using third party classes

I have a method that I have to write the junit for
public String getSomething(String no)
{
ThirdPartyClass.Innerclass innerclass = new ThirdPartyClass.Innerclass(..);
String result = innerClass.getSomething(no);
}
I know how to set the private fields in a class using the Whitebox. How can i mock the ThirdPartyClass and ThirdPartyClass.Innerclass
Two options here.
First and best is to not call new in the method. Pass in an InnerClass factory instance to the constructor of the class under test. Then mock this factory.
Second, use a mocking framework like Powermock which can intercept and mock constructor calls.
Mock Constructor

How to mock Objects that are not passed as arguments

Imagine the following class
public class ClassToBeTested{
private AnotherClass otherClass;
public void methodToBeTested(){
otherClass = new AnotherClass();
String temp = otherClass.someMethod()
// ...some other code that depends on temp
}
}
Now, if methodToBeTested was designed to accept an instance of AnotherClass I could easily create a mock of AnotherClass and tell Mockito to return a value i prefeer when someMethod() is called. However as the above code is designed AFAIK it's not possible to mock AnotherClass and testing this method will depend on what someMethod() returns.
Is there anyway I can test the above code without beeing dependent on what someMethod() returns using Mockito or any other framework?
If available you can use the Spring ReflectionTestUtils setField method:
http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html#setField%28java.lang.Object,%20java.lang.String,%20java.lang.Object%29
If not write your own its pretty straight forward using reflection, some info here:
http://www.java2s.com/Code/Java/Reflection/Setprivatefieldvalue.htm
Something like the below, you will need additional error handling to get this to work properly:
public void setField(Object obj, String fieldName, Object value) {
Field f = obj.getDeclaredField(fieldName);
f.setAccessible(true);
f.set(obj, value);
}
It can then be called like this:
setField(objUnderTest, "fieldToSet", mockObject);
edit
I have just noticed that you are instantiating it inside the method. If that is absolutely necessary then you should follow the possible duplicate link posted by cyroxx.
Although that practice is often a sign of bad design so if you can take it out I would.
Setting the field by reflection as suggested in the other answer will work.
But if you're doing this sort of thing often, I'd recommend PowerMock (in conjunction with Mockito) or JMockIt to achieve this. Both allow you to mock constructors, statics, final fields... in short, just about anything. Very useful with legacy code.
However, when you're writing new code, and your class has a dependency on another class that you want to isolate in this way, you should consider changing the design so that the other object is passed in to your class instead of being instantiated by it. Search for "Dependency injection" and you'll find plenty...
As a quick fix, I usually wrap the call to new:
protected newAnotherClass() { return new AnotherClass(); }
That way, I can overwrite this method from a unit test. It's dirty but it's quick :-)
Here is a JMockit test which does what you want, very simply:
#Test
public void testTheMethodToBeTested(#Mocked final AnotherClass dep)
{
new NonStrictExpectations() {{ dep.someMethod(); result = "whatever"; }};
new ClassToBeTested().methodToBeTested();
new Verifications() {{
// verify other calls to `dep`, if applicable...
}};
}

Unexpected method call while doing the unit testing with EasyMock

I am testing mail functionality in my code with the UnitilsJUnit4 and EasyMock.
My code is like this..
public void prepare(MimeMessage mimeMessage) {
// some code ..
MimeMessageHelper message = new MimeMessageHelper( mimeMessage, true );
// some mail settings ..
}
when I am testing the method prepare, it is giving the below exception.. but the method it is showing below is from the Spring framework class.
java.lang.AssertionError:
Unexpected method call setContent(javax.mail.internet.MimeMultipart#6e616e61):
setContent(javax.mail.internet.MimeMultipart#2dda2dda): expected: 1, actual: 0
at $javax.mail.internet.MimeMessage$$EnhancerByCGLIB$$614de43f.setContent(<generated>)
at org.springframework.mail.javamail.MimeMessageHelper.createMimeMultiparts(MimeMessageHelper.java:344)
at org.springframework.mail.javamail.MimeMessageHelper.<init>(MimeMessageHelper.java:290)
at org.springframework.mail.javamail.MimeMessageHelper.<init>(MimeMessageHelper.java:247)
at org.springframework.mail.javamail.MimeMessageHelper.<init>(MimeMessageHelper.java:226)
Please help me to resolve the above issue.. how to test my method?
I know this was written a long time ago, but I just encountered this exact same problem.
If you can mock the MimeMessageHelper in some form you can easily test the code. I did this by creating an interface that simply supplies back the MimeMessageHelper class and adding that as a dependency to the class I was testing.
Interface:
public interface MimeMessageHelperProvider {
MimeMessageHelper getMimeMessageHelper(MimeMessage mimeMessage);
}
Implementation:
public class MimeMessageHelperProviderImpl implements MimeMessageHelperProvider {
#Override
public MimeMessageHelper getMimeMessageHelper(MimeMessage mimeMessage) {
return new MimeMessageHelper(mimeMessage);
}
}
Now you can wire in the MimeMessageHelperProvider and simply mock that interface to have it return you an instance you can verify against.
You seem to be mocking the wrong thing. You're mocking the Mail API when you should be mocking the Spring class, since that's what you interact with directly. The way you're doing it now, you're effectively testing the Spring class along with your own, which isn't really what you want.
You need to mock the MimeMessageHelper. You can't inject it because it takes mimeMessage in the constructor. So to do this you need something like PowerMock.
From the documentation:
Use the #RunWith(PowerMockRunner.class) annotation at the
class-level of the test case.
Use the #PrepareForTest(ClassThatCreatesTheNewInstance.class)
annotation at
the class-level of the test case.
Use
PowerMock.createMock(NewInstanceClass.class) to create a mock
object
of the class that should be constructed (let's call it
mockObject).
Use
PowerMock.expectNew(NewInstanceClass.class).andReturn(mockObject)
to
expect a new construction of an object of type
NewInstanceClass.class but instead return the mock object.
Use
PowerMock.replay(mockObject, NewInstanceClass.class) to change the
mock object and class to replay mode, alternatively use the
PowerMock.replayAll() method.
Use PowerMock.verify(mockObject,
NewInstanceClass.class) to change the mock object and class to
verify mode, alternatively use the PowerMock.verifyAll() method.
Obviously, I don't really know what you're trying to test, but your test would look something like:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MessagePreparer.class)
public class MessagePreparerTest {
#Test
public void testPrepare() {
MimeMessage mockMessage = PowerMock.createMock(MimeMessage.class);
MimeMessageHelper mockMessageHelper = PowerMock.createMock(MimeMessageHelper.class);
PowerMock.expectNew(MimeMessageHelper.class,
mockMessage, true).andReturn(mockMessageHelper);
// ...set other expectations
PowerMock.replay(mockMessage, mockMessageHelper, MimeMessageHelper.class);
MessagePreparer messagePreparer = new MessagePreparer();
messagePreparer.prepare(mockMessage);
PowerMock.verify(mockMessage, mockMessageHelper, MimeMessageHelper.class);
}
}

Categories