我想模拟@PostConstruct
内部的方法调用。
在正常应用程序启动期间,这将从数据库中初始化一些数据。
但是在测试或集成测试中,我想模拟该数据库调用,并返回模拟的Set<String>
。
问题:@PostConstruct
总是在@Before
方法中设置模拟之前被调用:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MockITest {
@MockBean
private DatabaseService db;
@Autowird
private MyService service; //the service to test
@Before
public void setup() {
given(db.findAllByName()).willReturn(Set.of("john", "doe"));
}
@Test
public void testServiceInPostConstructIsMocked() {
service.run();
}
}
public class MyService {
@Autowired
private DatabaseService db;
private Set<String> names;
//initialization on startup, and cache the results in the member field
@PostConstruct
public void init() {
names = db.findAllByName();
}
public void run() {
System.out.println(names); //always empty for the test
}
}
如何仍能正确模拟数据库服务?
答案 0 :(得分:0)
根本原因似乎是在进行任何弹簧初始化并且后处理完成之后应用了@MockBean
。因此也在@PostConstruct
之后。
因此,我将“名称”缓存移入数据库服务本身,如下所示:
@Service
public class DatabaseService {
private Set<String> names;
public Set<String> findAllByName() {
if (names == null) {
names = dao.executeSql(...);
}
return names;
}
}
public class MyService {
public void run() {
//now when this is called, the mock is already available
System.out.println(db.findAllByName());
}
}
试图将内容缓存在MyService
中也许是不好的代码,这就是为什么junit和mockito强制将其实现为不同的方式?