Unit Testing with Mockito for Constructors

Unit testing with mockito for constructors

Once again the problem with unit-testing comes from manually creating objects using new operator. Consider passing already created Second instead:

class First {

private Second second;

public First(int num, Second second) {
this.second = second;
this.num = num;
}

// some other methods...
}

I know this might mean major rewrite of your API, but there is no other way. Also this class doesn't have any sense:

Mockito.when(new Second(any(String.class).thenReturn(null)));

First of all Mockito can only mock methods, not constructors. Secondly, even if you could mock constructor, you are mocking constructor of just created object and never really doing anything with that object.

Mockito: how to test that a constructor was called?

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!

Mock a constructor with parameter

The code you posted works for me with the latest version of Mockito and Powermockito. Maybe you haven't prepared A?
Try this:

A.java

public class A {
private final String test;

public A(String test) {
this.test = test;
}

public String check() {
return "checked " + this.test;
}
}

MockA.java

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class MockA {
@Test
public void test_not_mocked() throws Throwable {
assertThat(new A("random string").check(), equalTo("checked random string"));
}
@Test
public void test_mocked() throws Throwable {
A a = mock(A.class);
when(a.check()).thenReturn("test");
PowerMockito.whenNew(A.class).withArguments(Mockito.anyString()).thenReturn(a);
assertThat(new A("random string").check(), equalTo("test"));
}
}

Both tests should pass with mockito 1.9.0, powermockito 1.4.12 and junit 4.8.2

Mock constructor with mockito

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.

Mock static method called from constructor in java class

So to answer your question how to mock a static method: mockito allows this since version 3.8.0. You can find a tutorial here at Baeldung

This allows generating a statically mocked Object for a concrete context, which you can create within a try block. For your case this would look like the following.

Fixed Unit Test

package com.javaeasily.demos.junit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class MyClassTest {
private MyClass myclass;

@BeforeEach
public void SetUp() {
try (MockedStatic<NodeUtils> nodeUtilsMockedStatic = Mockito.mockStatic(NodeUtils.class)) {
nodeUtilsMockedStatic.when(NodeUtils::getMyNode).thenReturn("foo");
myclass = new MyClass();
}
}

@Test
public void testReconfigureNode() {
myclass.reconfigureNode();
}
}

Mockito dependency

You need mockito with at least version 3.8.0 in your project.

With maven add:

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>

With gradle add:

testImplementation group: 'org.mockito', name: 'mockito-inline', version: '3.8.0'


Related Topics



Leave a reply



Submit