Java 单元测试时如何跳过@PostConstruct
我有一个每天晚上收集数据的计划任务。每当我启动应用程序时,任务就会运行,当我在应用程序上运行jUnit测试时,我想停止它的运行Java 单元测试时如何跳过@PostConstruct,java,spring,junit4,postconstruct,Java,Spring,Junit4,Postconstruct,我有一个每天晚上收集数据的计划任务。每当我启动应用程序时,任务就会运行,当我在应用程序上运行jUnit测试时,我想停止它的运行 @Scheduled(cron = "0 0 0 1 * ?") public void SalesDataAggregation() { //aggregation } 编辑 上面的方法也在这里被调用 @PostConstruct public void init(){ SalesDataAggregation(); } 由于@PostConstr
@Scheduled(cron = "0 0 0 1 * ?")
public void SalesDataAggregation() {
//aggregation
}
编辑
上面的方法也在这里被调用
@PostConstruct
public void init(){
SalesDataAggregation();
}
由于@PostConstruct注释,方法SalesDataAggregate在启动时运行。如果希望在测试期间不让它运行,可以在测试文件夹中创建包含post构造的类,并添加@primary注释,使其优先于主项目中的类
@Primary
public class ClassContainingPostConstruct{
}
由于@PostConstruct注释,方法SalesDataAggregate在启动时运行。如果希望在测试期间不让它运行,可以在测试文件夹中创建包含post构造的类,并添加@primary注释,使其优先于主项目中的类
@Primary
public class ClassContainingPostConstruct{
}
您可以将包含bean的
PostConstruct
重新写入EventListener
()以在启动时触发,我认为这就是本文的目的。然后,该bean可以绑定到特定的配置文件,以仅在特定启用的配置文件上触发
另一种选择是使用属性有条件地触发它
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的好处,您可以将包含bean的PostConstruct
重新写入EventListener
()以在启动时触发,我假设这就是它的目的。然后,该bean可以绑定到特定的配置文件,以仅在特定启用的配置文件上触发
另一种选择是使用属性有条件地触发它
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的好处在我的情况下,我的PostConstruct中没有任何内容会使我的其他测试崩溃,只有我的Mockito.verify,因此我决定保留PostConstruct使用的注入的mock类,然后在我的测试中,使用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);
}
}
在我的例子中,PostConstruct中没有任何内容会使我的其他测试崩溃,只有Mockito.verify,因此我决定保留PostConstruct使用的注入的mock类,然后在我的测试中,使用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);
}
}
根据此处的代码,您的@计划的
代码不应在启动时运行。这个方法是在其他地方调用的吗?它是在其他地方调用的。我在触发该方法的PostConstruct
上方添加了代码。实际上,它似乎不适合于构造后调用。可能是启动时触发的某种事件侦听器,可以放在配置文件中?我认为您最好将问题改为“单元测试时如何跳过@PostConstruct”,这不是计划问题……基于此处的代码,您的@scheduled
代码不应该在启动时运行。这个方法是在其他地方调用的吗?它是在其他地方调用的。我在触发该方法的PostConstruct
上方添加了代码。实际上,它似乎不适合于构造后调用。可能是启动时触发的某种事件侦听器,可以放在配置文件中?我认为您最好将问题改为“单元测试时如何跳过@PostConstruct”,这不是一个计划问题……这不会起作用。Spring将报告:“bean类与现有的、不兼容的同名bean定义冲突”,这将不起作用。Spring将报告:“bean类与现有的、不兼容的同名bean定义冲突”