代码之家  ›  专栏  ›  技术社区  ›  membersound

如何在@PostConstruct中模拟豆子?

  •  1
  • membersound  · 技术社区  · 7 年前

    我想在内部模拟一个方法调用 @PostConstruct . 在正常的应用程序启动期间,这会初始化数据库中的一些数据。

    但在测试或集成测试期间,我想模拟该数据库调用并返回我的模拟结果 Set<String> 相反

    问题: @施工后 总是在中设置模拟之前调用 @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
        }
    }
    

    我怎样才能正确地模拟数据库服务?

    1 回复  |  直到 7 年前
        1
  •  0
  •   membersound    7 年前

    根本原因似乎是 @MockBean 在任何spring初始化和后处理完成后应用。这样之后 @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强制以不同的方式实现它?