Java 单元测试:定义模拟行为后调用@PostConstruct

Java 单元测试:定义模拟行为后调用@PostConstruct,java,spring,unit-testing,mockito,postconstruct,Java,Spring,Unit Testing,Mockito,Postconstruct,我有两门课: public MyService { @Autowired private MyDao myDao; private List<Items> list; @PostConstruct private void init(){ list = myDao.getItems(); } } 单元测试: @ContextConfiguration("/test-context.xml") @Run

我有两门课:

public MyService {
    @Autowired
    private MyDao myDao;     
    private List<Items> list; 

    @PostConstruct
    private void init(){
         list = myDao.getItems(); 
    }
}
单元测试:

@ContextConfiguration("/test-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {

    @Autowired 
    MyService myService

    @Autowired 
    MyDao myDao;

    @Resource
    @Qualifier("responseItems")
    private List<Item> responseItems; 

    @Before
    public void setupTests() {
        reset(myDao); 
        when(myDao.getItems()).thenReturn(responseItems); 
    }
}
@ContextConfiguration(“/test context.xml”)
@RunWith(SpringJUnit4ClassRunner.class)
公共类MyServiceTest{
@自动连线
我的服务我的服务
@自动连线
MyDao MyDao;
@资源
@限定词(“responseItems”)
私有列表响应;
@以前
公共测试(){
重置(myDao);
when(myDao.getItems())。然后return(responseItems);
}
}
这样做的问题是创建了
MyService
bean,并且在定义模拟行为之前调用了它的@PostConstruct bean


如何在XML中定义模拟行为,或者将
@PostConstruct
延迟到单元测试设置之后?

MyDao听起来像是外部系统的抽象。通常,不应在
@PostConstruct
方法中调用外部系统。相反,您的
getItems()
MyService
中的另一个方法调用


Mockito注入将在Spring启动之后进行,此时mock不会像您看到的那样工作。您不能延迟
@PostConstruct
。要克服这一点并自动运行加载,请使用
MyService
实现
SmartLifecycle
并在
start()
中调用
getItems()
,我的项目中也有类似的需求。我需要使用@PostConstructor设置一个字符串,我不想运行spring上下文,或者换句话说,我想要简单的模拟。我的要求如下:

public class MyService {

@Autowired
private SomeBean bean;

private String status;

@PostConstruct
private void init() {
    status = someBean.getStatus();
} 
}

解决方案:

public class MyServiceTest(){

@InjectMocks
private MyService target;

@Mock
private SomeBean mockBean;

@Before
public void setUp() throws NoSuchMethodException,  InvocationTargetException, IllegalAccessException {

    MockitoAnnotations.initMocks(this);

    when(mockBean.getStatus()).thenReturn("http://test");

    //call post-constructor
    Method postConstruct =  MyService.class.getDeclaredMethod("init",null); // methodName,parameters
    postConstruct.setAccessible(true);
    postConstruct.invoke(target);
  }

}

是的-我想你可能是对的,通常我的问题表明我应该解决一种代码气味。完美的解决方案
public class MyServiceTest(){

@InjectMocks
private MyService target;

@Mock
private SomeBean mockBean;

@Before
public void setUp() throws NoSuchMethodException,  InvocationTargetException, IllegalAccessException {

    MockitoAnnotations.initMocks(this);

    when(mockBean.getStatus()).thenReturn("http://test");

    //call post-constructor
    Method postConstruct =  MyService.class.getDeclaredMethod("init",null); // methodName,parameters
    postConstruct.setAccessible(true);
    postConstruct.invoke(target);
  }

}