单元测试时如何跳过@PostConstruct

时间:2018-07-31 16:32:34

标签: java spring junit4 postconstruct

我有一个计划的任务,每天晚上汇总数据。每当我启动应用程序时,任务便会运行,而当我在应用程序上运行jUnit测试时,我想停止其运行。

@Scheduled(cron = "0 0 0 1 * ?")
public void SalesDataAggregation() {
    //aggregation
}

修改

上面的方法也在这里被调用

@PostConstruct
public void init(){
    SalesDataAggregation();
}

3 个答案:

答案 0 :(得分:1)

由于 @PostConstruct 批注,方法 SalesDataAggregate 在启动时正在运行。如果要使其在测试期间不运行,则可以在测试文件夹中创建包含post构造的类,并添加 @primary 批注,以便它优先于主项目中的类。

@Primary
public class ClassContainingPostConstruct{   

}

答案 1 :(得分:0)

您可以将包含PostConstruct的bean重新编写为EventListenerhttps://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2)以便在启动时触发,我想这就是它的目的。然后可以将该bean绑定到某些Profile上,以仅在特定启用的配置文件上触发。

另一种选择是使用属性有条件地触发它。

public class PostConstructBean {

public boolean isPostConstructEnabled;

public PostConstructBean(@Value("${postconstructenabled}" String value){
   isPostConstructEnabled = Boolean.parseBoolean(value);
}

@PostConstruct
public void init(){
   if(isPostConstructEnabled){
      SalesDataAggregation();
   }else{
      //NOOP
   }
}
}

然后将属性添加到您的环境属性/整体属性文件中。这增加了好处,使您可以更轻松地加载/禁用Bean

答案 2 :(得分:0)

在我的情况下,PostConstruct中的任何内容都不会使其他测试崩溃,只有Mockito.verify崩溃,因此我决定保留PostConstruct使用的注入的模拟类,然后在测试中重新模拟并重新注入它使用Mockito和ReflectionTestUtils。这避免了bean创建的问题,并允许我仅验证刚刚模拟的类:

被测类:

@Component
public class ClassUnderTest
{
    @Autowired
    private MockedClass nameOfActualBeanInClassUnderTest;

    @PostConstruct
    private void postConstructMethod()
    {
        Object param1 = new Object();
        Object param2 = new Object();
        this.nameOfActualBeanInClassUnderTest.mockedClassFunctionBeingHit(param1, param2);
    }
}

测试类:

import static org.mockito.Mockito.*;
import org.springframework.test.util.ReflectionTestUtils;

public class Tests
{
    // Class Under Test
    @Autowired
    private ClassUnderTest classUnderTest;

    // Mocked Class
    @MockBean
    private MockedClass mockedClass;

    @Test
    public void actualTestThatAvoidsPostConstruct()
    {
        // ============== Ignore PostConstruct Errors ==============

        // Note: You will probably want to capture the current mocked class
        // to put it back in the class under test so that other tests won't fail
        MockedClass savedMockedClass = 
        (MockedClass)ReflectionTestUtils.getField(this.classUnderTest,
            "nameOfActualBeanInClassUnderTest");

        this.mockedClass = mock(MockedClass.class);
        ReflectionTestUtils.setField(this.classUnderTest,
            "nameOfActualBeanInClassUnderTest",
            this.mockedClass);

        // ============== Setup Test ==============
        Object response = new Object();

        // Set return value when mockedClass' function is hit
        // Note: Only need to pass params if your function actually has them
        when(this.mockedClass.mockedClassFunctionBeingHit(param1, param2))
            .thenReturn(response);

        // ============== Test ==============

        this.classUnderTest.testFunction();

        // ============== Verify ==============

        // Note: Only need to pass params if your function actually has them
        verify(this.mockedClass).mockedClassFunctionBeingHit(param1, param2);

        // ============== Reset Mocked Class ==============
        ReflectionTestUtils.setField(this.classUnderTest,
            "nameOfActualBeanInClassUnderTest",
            savedMockedClass);
    }
}
相关问题