我想为Spring Data存储库编写集成测试,并想知道在测试类中使存储库可用的首选方法是什么。
在测试我自己的普通旧服务时,我使用这样的东西来避免使用字段注入,因为不应该使用字段注入according to Spring Data project lead Oliver Gierke:
public class myServiceTest {
private MyService myService;
@Before
public void setUp() {
myService = new MyService();
}
[...]
}
但Spring Data存储库被定义为没有实现的接口,因为Spring魔法会动态创建实现。
public interface FruitRepository extends CrudRepository<Fruit, Long> {
List<Fruit> findByName(String name);
}
因此我没有像这样使用的构造函数。
使用构造函数注入(如下面的示例)也不起作用,因为在尝试运行测试时会产生异常:
@Autowired
public MyServiceTest(MyService myService) {
this.myService = myService;
}
java.lang.Exception: Test class should have exactly one public zero-argument constructor
据我所知,我留下的唯一选择是通过字段注入注入存储库,如下面的工作示例所示:
@RunWith(SpringRunner.class)
@SpringBootTest
public class FruitRepositoryTest {
@Autowired
private FruitRepository fruitRepository;
@Test
public void findByNameFindsAnExistingFruit() {
fruitRepository.deleteAll();
fruitRepository.save(new Fruit("Orange"));
List<Fruit> foundFruits = fruitRepository.findByName("Orange");
assertFalse(foundFruits.isEmpty());
}
@Test
public void findByNameDoesNotFindANonExistingFruit() {
fruitRepository.deleteAll();
fruitRepository.save(new Fruit("Apple"));
List<Fruit> foundFruits = fruitRepository.findByName("Orange");
assertTrue(foundFruits.isEmpty());
}
}
所以,我的问题是:这是规则的合法例外,以避免现场注入或我错过了什么?或者我是否可能过度思考这一点,因为无论如何现场注入都可以在测试类中使用?
答案 0 :(得分:1)
对于测试,这非常好。
使用当前版本的JUnit,实际上没有合理的方法可以采用不同的方式。
更喜欢构造函数注入的一点是,其他代码片段可以在不使用任何反射魔法的情况下正确实例化类。但除了JUnit之外,没有人会尝试实例化你的测试,所以论证是无效的。
Spring Data本身的集成测试使用这种方法。例如,请参阅https://github.com/spring-projects/spring-data-jpa/blob/master/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java#L97请注意,Oliver是作者之一,所以我猜他也同意。