Search code examples
spring-bootmockitojunit5spring-boot-test

Argument passed to when() is not a mock! exception thrown with Spring Boot project which doesn't have @SpringBootApplication/main class


My project is a simple spring boot application which doesn't have a main/@SpringBootApplication class. It is used as a dependency library for other modules. I am trying to write the unit tests for the classes present in this project like below and getting the below pasted error. Any quick help is much appreciated.

pom dependencies:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        
        <!-- exclude junit 4 -->
        <exclusions>
            <exclusion>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
     <!-- junit 5 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <scope>test</scope>
    </dependency>

As this project doesn't have main class, to get the spring application context using below configuration class.

@Configuration
public class TestServiceConfig {
@Bean
public TestService productService() {
    return Mockito.mock(TestService.class);
}

@Bean
public MongoDriverService productMongo() {
    return Mockito.mock(MongoDriverService.class);
}
}

Below is my test class which is throwing exception. Actual java class has a method called getPlanCode(which takes 6 arguments) and returns void. In this method mongo object is used for connecting the db so that I used @InjectMocks on service object.

public class ValidationServiceTest {
@Mock
MongoDriverService mongo;

@InjectMocks
TestService service;

@Test
@DisplayName("Test Get Plan Code positive")
public void getPlanCodeTest() {
    doNothing().when(service).getPlanCode(anyString(), anyString(), any(Batch.class), any(BatchFile.class), any(Document.class), anyString());
    
    service.getPlanCode(anyString(), anyString(), any(Batch.class), any(BatchFile.class), any(Document.class), anyString());

    verify(service, times(1)).getPlanCode(anyString(), anyString(), any(Batch.class), any(BatchFile.class), any(Document.class), anyString());
    
}
}

Below is the exception

12:51:33.829 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - After test method: context [DefaultTestContext@45b4c3a9 testClass = DefaultMedicareBFTAccumsValidationServiceTest, testInstance = com.anthem.rxsmart.service.standalone.batchvalidation.DefaultMedicareBFTAccumsValidationServiceTest@14dda234, testMethod = getPlanCodeTest@DValidationServiceTest, testException = org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to when() is not a mock!
Example of correct stubbing:

Solution

  • service is not a mock since you are using @InjectMocks ( assume you are using @RunWith(MockitoRunner.class) or @ExtendWith but you are hiding that for whatever reasons).

    What @InjectMocks does, is create of a new instance of TestService and literally inject mocks into it (mocked required dependencies). So service is a real thing, not a mock

    IMO this test makes not sense as you are suppose to test your implementation of singular entity contract, not to test mocks...

    Your test case and assertions are pointless as it is like "call method A and check if I just called method A" while you should check and validate eg return value of a call, or if some methods of mocks have been called eg if Mongo was queried with proper arguments. I just hope it is a really bad example, not real test scenario

    Also test setup is wrong as you show us that you want to use @Configuration class with @Bean but then you are using @Mock in the test which will create brand new mocks for you. In other words - that config is not used at all