Search code examples
springspring-bootjunitmockito

when(..) stub of service method does not work in Mockito Unit Test


Why doesn't the following when stub of a service method work? I see that when I run the test, the real ar11applicationService's processEligibleRecords is called, not the stub that I created. I am testing an Application whose run will call the Service method. The anyString/anyInt param options are used to create the stub.

@SpringBootTest
@RunWith(MockitoJUnitRunner.class) 
@ExtendWith(MockitoExtension.class)
class Ar11ApplicationTest {

    @Mock
    Ar11ApplicationService ar11ApplicationService;
    
    @Mock
    EmailService emailService;
    
    @InjectMocks   // inject into the object we're testing
    Ar11Application ar11Application;
    
    @BeforeEach
    void setUp() throws Exception {
        
        // This is the stub that should get called - 9 params, next-to-last is Int, all others String
        Mockito.when(ar11ApplicationService.processEligibleRecords(Mockito.anyString(), Mockito.anyString(), 
                                                                   Mockito.anyString(), Mockito.anyString(), 
                                                                   Mockito.anyString(), Mockito.anyString(), 
                                                                   Mockito.anyString(), Mockito.anyInt(), Mockito.anyString()))
              .thenReturn(new Ar11ResultBean());
    }

    @Test
    void main() throws Exception {
        
        org.junit.jupiter.api.Assertions.assertDoesNotThrow(
                  ()-> 
                  {
                      ar11Application.run(new String[] {});
                  }
                );
    }

}

Service Implementation class's method (Ar11ApplicationServiceImpl implements Ar11ApplicationService):

@Component
public class Ar11ApplicationServiceImpl implements Ar11ApplicationService {

@Override
@Transactional(readOnly = false, rollbackFor = Exception.class)
public Ar11ResultBean processEligibleRecords(String eligibleFilename, String newFilename, 
                                             String sourceDir, String sftpUserName, 
                                             String sftpPrivateKeyPath, String sftpPrivateKeyPassphrase, 
                                              String sftpHost, Integer sftpPort, String remoteDir) 
 throws Exception {

The application class that I'm testing is

@SpringBootApplication
public class Ar11Application implements CommandLineRunner {
    

// General properties
@Value("${AR11_ELIGIBLE_FILENAME}")
private String eligibleFilename;    
@Value("${AR11_NEW_FILENAME_PREFIX}")
private String newFilenamePrefix;

// SFTP properties  
@Value("${AR11_SFTP_USERNAME}")
private String sftpUserName;    
@Value("${AR11_SFTP_KEY_PATH}")
private String sftpPrivateKeyPath;  
@Value("${AR11_SFTP_PASSPHRASE}")
private String sftpPrivateKeyPassphrase;
@Value("${AR11_SFTP_HOST}")
private String sftpHost;    
@Value("${AR11_SFTP_PORT}")
private Integer sftpPort;
@Value("${AR11_SFTP_SOURCE_DIR}")
private String sourceDir;
@Value("${AR11_SFTP_TARGET_DIR}")
private String remoteDir;   

    @Autowired
    Ar11ApplicationService ar11ApplicationService;

@Override
public void run(String... args) throws Exception {
    
try {
    Ar11ResultBean ar11ResultBean = ar11ApplicationService.processEligibleRecords(eligibleFilename, newFilename, sourceDir,  
                                                                                  sftpUserName, sftpPrivateKeyPath, sftpPrivateKeyPassphrase, sftpHost, sftpPort, remoteDir);

Solution

  • The answer, per @tgdavies, was to remove @SpringBootTest at the top. It should be this:

    @RunWith(MockitoJUnitRunner.class) // No @SpringBootTest!
    @ExtendWith(MockitoExtension.class)
    class Ar11ApplicationTest {
    
        @Mock
        Ar11ApplicationService ar11ApplicationService;
        
        @Mock
        EmailService emailService;
        
        @InjectMocks
        Ar11Application ar11Application;
        
        @BeforeEach
        void setUp() throws Exception {
            
            Mockito.when(ar11ApplicationService.processEligibleRecords(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt(), Mockito.anyString()))
                 .thenReturn(new Ar11ResultBean(500));
    

    I verified in the debugger that as soon as @SpringBootTest is added, it immediately goes to the real Service class's code without even doing setUp in this unit test. Thanks for the help.