Mockito not mocking my @Autowired class

时间:2018-07-24 10:05:41

标签: spring unit-testing spring-boot mockito testng

I came across a problem, while mocking my class i get NullPointerException on mocked object and I cant figure out why mockito is not mocking only one class annotated by @Mock. Do someone have any idea what's the problem there ?

Tested class :

public class TimeoutJpaTransactionManager extends JpaTransactionManager {

    private final String TRANSACTION_METHOD_NAME= String.join(".", ZapisPakietuReceptService.class.getName(), "transactionMethod");

    @Autowired
    private TransactionTimeoutConfig transactionTimeoutConfig;

    public TimeoutJpaTransactionManager(EntityManagerFactory emf) {
        super(emf);
    }

    protected int determineTimeout(TransactionDefinition definition) {
        if (TRANSACTION_METHOD_NAME.equals(definition.getName())) {
            return transactionTimeoutConfig.getSgr();
        }

        return super.getDefaultTimeout();
    }
}

Autowired class :

@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "transaction.timeout")
public class TransactionTimeoutConfig {

    private int sgr;
}

Test class:

public class TimeoutJpaTransactionManagerTest {

    @InjectMocks
    private TimeoutJpaTransactionManager timeoutJpaTransactionManager;

    @Mock
    private EntityManagerFactory entityManagerFactory;

    @Mock
    private TransactionDefinition transactionDefinition;

    @Mock
    private TransactionTimeoutConfig transactionTimeoutConfig;

    private final String TRANSACTION_METHOD_NAME_MOCK= String.join(".", ZapisPakietuReceptService.class.getName(), "transactionMethod");
    private final int TIMEOUT_VALUE= 30;

    @BeforeMethod
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testDetermineTimeout() {
        //given
        Mockito.when(transactionDefinition.getName()).thenReturn(TRANSACTION_METHOD_NAME_MOCK);
        Mockito.when(transactionTimeoutConfig.getSgr()).thenReturn(TIMEOUT_VALUE);

        //when
        int result = timeoutJpaTransactionManager.determineTimeout(transactionDefinition);

        //then
        Assertions.assertThat(result).isEqualTo(TIMEOUT_VALUE);
    }
}

Whats weird and i cant undestand is that by adding another line like that all seems to work and TransactionDefinition is really mocked :

@BeforeMethod
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.initMocks(this);
    }

1 个答案:

答案 0 :(得分:0)

由于M. Deinum的评论,我得以弄清楚,看来问题出在混合字段和构造函数注入。解决方案是将依赖关系移至构造函数,然后将其连接到那里,或将当前测试用例修改为

@InjectMocks
    private TimeoutJpaTransactionManager timeoutJpaTransactionManager;

    @Mock
    private TransactionDefinition transactionDefinition;

    @Mock
    private TransactionTimeoutConfig transactionTimeoutConfig;

    private EntityManagerFactory entityManagerFactory;

    private final String TRANSACTION_METHOD_NAME_MOCK= String.join(".", ZapisPakietuReceptService.class.getName(), "transactionMethod");
    private final int TIMEOUT_VALUE= 30;

    @BeforeMethod
    public void setUp() {
        entityManagerFactory = Mockito.mock(EntityManagerFactory.class);
        timeoutJpaTransactionManager = new TimeoutJpaTransactionManager(entityManagerFactory);
        MockitoAnnotations.initMocks(this);
    }