Spring JUnit测试:复用TestsDataPreparer的Repository是否可行?
问题描述
我有一个标注了@Component的TestsDataPreparer类,原本以私有方式注入CarRepository:
@Component class TestsDataPreparer( private val carRepository: CarRepository ) { fun withCar(builder: Car.() -> Unit = {}): Car { return carRepository.save( Car( name = builder.name!! ) ) } }
这种写法清晰易懂。但我想知道,改成以下将CarRepository设为公开属性的写法是否可行,或是被视为反模式:
@Component class TestsDataPreparer( val carRepository: CarRepository ) { fun withCar(builder: Car.() -> Unit = {}): Car { return carRepository.save( Car( name = builder.name!! ) ) } }
并在测试类中不直接注入Repository,而是通过TestsDataPreparer实例复用它:
@Test fun testCar() { testsDataPreparer.withCar{this.name="Super-cool-car!"} assertThat(testsDataPreparer.carRepository.findAll()).hasSize(1) }
我的问题是:不在测试类中直接注入Repository,而是从TestsDataPreparer类复用它是否可行?
回答
- 这种写法可行,但属于代码设计上的坏味道,不推荐使用
- 核心问题在于破坏了封装性:
TestsDataPreparer的职责是封装测试数据的准备逻辑,暴露内部依赖的CarRepository会模糊它的职责边界,让外部代码(测试类)可以直接操作底层数据组件,违背了单一职责原则 - 可维护性变差:如果后续修改
TestsDataPreparer的内部实现(比如替换CarRepository为其他数据操作类),所有直接依赖它暴露的Repository的测试代码都会失效,需要同步修改 - 测试意图隐晦:测试类应该直接依赖它需要验证的核心组件(
CarRepository),通过中间类间接调用会让测试的逻辑意图变得不清晰,其他开发者阅读测试代码时需要额外梳理TestsDataPreparer的内部结构
更合理的做法有两种:
- 直接在测试类中注入
CarRepository,明确测试依赖 - 在
TestsDataPreparer中添加专门的数据查询方法,保持类的封装性,同时满足测试需求:
@Component class TestsDataPreparer( private val carRepository: CarRepository ) { fun withCar(builder: Car.() -> Unit = {}): Car { return carRepository.save( Car( name = builder.name!! ) ) } // 添加专门的查询方法 fun getAllCars(): List<Car> { return carRepository.findAll() } }
测试类中调用该方法:
@Test fun testCar() { testsDataPreparer.withCar{this.name="Super-cool-car!"} assertThat(testsDataPreparer.getAllCars()).hasSize(1) }
内容的提问来源于stack exchange,提问作者peter
相关产品推荐
相关产品推荐

