Developer
Developer

Reputation: 533

Mockito in spring boot does not mock object

I have a simple test case for which I am using Mockito in spring boot application.

userOperation.java

...
@Autowired
Validator nameValidator;

private boolean userOperation(String name) {
    NameStats nameStats = nameValidator.validate(name);
    if (!nameStats.isSuccess()) {
        throw new Exception();
    }
    return true;
}
...

Validator.java

public NameStats validate(String name)
{
    NameStats nameStats = new NameStats();
    // code goes here
    return nameStats;
}

testCase.java

...
@SpringBootTest
@RunWith(SpringRunner.class)
public class ImportFileOperationTest {

    @Mock
    Validator nameValidator;

    @Mock
    NameStats nameStats;

    @InjectMocks
    UserOperation operation;

    @Test
    public void  ConnectorDelegate0Test() {
        Mockito.when(nameValidator.validate(any(String.class))).thenReturn(nameStats);
        Mockito.when(nameStats.isSuccess()).thenReturn(true);
        operation.userOperation(restConsumerRequest);
    }

}
...

Error :

For the above test case, I am getting NullPointerException. While tracing I found out that below line of code in test returns the null value.

Mockito.when(nameValidator.validate(any(String.class))).thenReturn(nameStats);

Because of the null value, when it tries to call nameStats.isSuccess() it is throwing nullpointexception even I have mocked the response to this function as true.

Question : 1. Am I mocking the response right way? 2. Why the mocking function returns the null object?

Update :

testCase.java

@SpringBootTest
@RunWith(SpringRunner.class)
public class ImportFileOperationTest {

    @MockBean
    Validator nameValidator;

    NameStats nameStats;

    @InjectMocks
    @Resource
    UserOperation operation;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void  ConnectorDelegate0Test() {
        nameStats = new nameStats();
        Mockito.when(nameValidator.validate(any(String.class))).thenReturn(nameStats);
        Mockito.when(nameStats.isSuccess()).thenReturn(true);
        operation.userOperation(restConsumerRequest);
    }

}

I tried to create the object nameStats manually and expected validate function to return that object but still, it returns null.

Any help would be appreciated.

Upvotes: 6

Views: 15793

Answers (3)

Vuk Djapic
Vuk Djapic

Reputation: 886

Had a similar problem after upgrade to Spring Boot 2. The reason is explained here https://javadoc.io/static/org.mockito/mockito-core/3.3.3/org/mockito/ArgumentMatchers.html#any-java.lang.Class-

Since Mockito 2.1.0, only allow non-null instance of , thus null is not anymore a valid value.

So mock returns null, or empty list, because calls were set with anyString(), and object passed was null. To match value or null, use matcher any().

Upvotes: 2

Michal
Michal

Reputation: 2423

The test shall be either Mockito-driven or Spring-driven. Spring-driven would have @SpringBootTest and @RunWith(SpringRunner.class) class-level annotations and mocks would be declared with @MockBean or explicitly instantied with Mockito.initMocks. Mockito-driven test would have @RunWith(MockitoJUnitRunner.class) and mocks would be declared with @Mock and/or injected with @InjectMocks. Note the injection does not help when the instance such as NameStats is instantied with new in within the method.

The shown test does not have to be @SpringBootTest and therefore it could be written as Mockito-driven test like this:

@RunWith(MockitoJUnitRunner.class)
public class ImportFileOperationTest {

@Mock
Validator nameValidator;

@InjectMocks
UserOperation operation;

@Test
public void  connectorDelegateTest() {
    NameStats nameStats = new NameStats();
    nameStats.setStats(Stats.SUCCESS);
    Mockito.when(nameValidator.validate(any(String.class))).thenReturn(nameStats);

    operation.userOperation(restConsumerRequest);
}

Upvotes: 11

GnanaJeyam
GnanaJeyam

Reputation: 3170

You need to use @InjectMocks for all class types and @Mock need to be used for all associated attributes inside that class.

Example :

 class Product {

 ProductDetails  productDetails;

 }

 class ProductDetails {

 }

Sample Test case for above class :

@SpringBootTest
@RunWith(SpringRunner.class)
public class ProductTest {

    @Mock
    ProductDetails productDetails;

    @InjectMocks
    Product product;

}

Upvotes: 3

Related Questions