如何在@PostConstruct 之前调用@BeforeMethod 块

How to invoke @BeforeMethod block before @PostConstruct

下面写的是Spring单元测试代码。单元测试 @Before 方法没有被执行。因为它是直接 运行 @PostConstruct 我得到错误 Caused by: java.lang.IllegalArgumentException: rate must be positive 因为默认值是 0.00。我想设置一些值来请求最大限制,以便 postcontstruct 块顺利通过。我的代码有什么问题?请帮忙。

@Component
public class SurveyPublisher  {

    @Autowired
    private SurveyProperties surveyProperties;

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

    }

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

}

//单元测试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
    }

}

刚刚意识到在 Junit 回调方法之前总是 运行 postConstruct 方法导致 spring 优先。如文档中所述 -

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.

解决你的问题-

  1. 正如@chrylis 上面评论的那样,重构您的 SurveyPublisher 以使用构造函数注入来注入速率限制器。这样你就可以轻松测试了。
  2. 注入导致问题的 Mock/Spy bean
  3. 创建测试配置,为您提供 class 的实例,用作 @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);
                }
            };
        }
    }
    

这是最简单的方法。

@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;
}