Kiran
Kiran

Reputation: 879

How to invoke @BeforeMethod block before @PostConstruct

I am writing below Spring Unit test code. Unit test @Before method is not getting executed. Since it is directly running @PostConstruct i am getting erorrs Caused by: java.lang.IllegalArgumentException: rate must be positive because the default value is 0.00. I want to set some value to request max limit so that postcontstruct block will go through smoothly. what is wrong in my code? Please help.

@Component
public class SurveyPublisher  {

    @Autowired
    private SurveyProperties surveyProperties;

    @PostConstruct
        public void init() {
            rateLimiter = RateLimiter.create(psurveyProperties.getRequestMaxLimit());
        }

    }

    public void publish() {
        rateLimiter.acquire();
        // do something
    }

}

//Unit test class

public class SurveyPublisherTest  extends AbstractTestNGSpringContextTests {

    @Mock
    SurveyProperties surveyProperties;

    @BeforeMethod   
    public void init() {
        Mockito.when(surveyProperties.getRequestMaxLimit()).thenReturn(40.00);
    }

    @Test
    public void testPublish_noResponse() {
        //do some test
    }

}

Upvotes: 3

Views: 2419

Answers (2)

Amit Naik
Amit Naik

Reputation: 1073

Just realized it will always run postConstruct method before Junit callback methods cause spring takes the precedence. As explained in the documentation -

if a method within a test class is annotated with @PostConstruct, that method runs before any before methods of the underlying test framework (for example, methods annotated with JUnit Jupiter’s @BeforeEach), and that applies for every test method in the test class.

Solution to you issue -

  1. As @chrylis commented above refactor your SurveyPublisher to use constructor injection to inject the rate limiter. So you can then easily test.
  2. Inject Mock/Spy bean which is causing the problem
  3. Create test config to give you the instance of the class to use as @ContextConfiguration

    @Configuration
    public class YourTestConfig {
    
        @Bean
        FactoryBean getSurveyPublisher() {
            return new AbstractFactoryBean() {
                @Override
                public Class getObjectType() {
                    return SurveyPublisher.class;
                }
    
                @Override
                protected SurveyPublisher createInstance() {
                    return mock(SurveyPublisher.class);
                }
            };
        }
    }
    

Upvotes: 2

Kiran
Kiran

Reputation: 879

Here is the simple one worked.

@Configuration
@EnableConfigurationProperties(SurveyProperties.class)
    static class Config {
}


@ContextConfiguration(classes = {
        SurveyPublisherTest.Config.class })
@TestPropertySource(properties = { "com.test.survey.request-max-limit=1.00" })
public class SurveyPublisherTest extends AbstractTestNGSpringContextTests {

//Remove this mock
//@Mock
//SurveyProperties surveyProperties;
}

Upvotes: 0

Related Questions