@Autowired和@SpringBootTest是否应该在单元测试中使用?

时间:2019-10-01 20:45:38

标签: java spring spring-boot unit-testing

在我工作的项目中,我们已经通过以下方式初始化单元测试服务:

  1. 该服务所需的模拟依赖项。
  2. 使用构造函数创建服务。

类似这样的东西:

@RunWith(SpringRunner.class)
public class ServiceTest extends AbstractUnitTest {

  @Mock private Repository repository;
  private Service service;

  @Before
  public void init() {
    service = new Service(repository);
    when(repository.findById(any(Long.class))).thenReturn(Optional.of(new Entity()));
  }
}

但是我们的新开发人员建议使用@Autowired@SpringBootTest

@SpringBootTest(classes = ServiceTest.class)
@MockBean(classes = Repository.class)
@RunWith(SpringRunner.class)
public class ServiceTest extends AbstractUnitTest {

  @MockBean private Repository repository;
  @Autowired private Service service;

  @Before
  public void init() {
    when(repository.findById(any(Long.class))).thenReturn(Optional.of(new Entity()));
  }
}

在此之前,我认为@Autowired@SpringBootTest仅应在集成测试中使用。但是用Google搜索很多,我发现有人在单元测试中使用了这两个。 我读了boot-features-testing。另外,我阅读了此Unit tests vs integration tests with Spring。 对我来说,我们仍然需要让Spring参与单元测试的依赖注入,因为我们可以自己完成单元测试。 因此,应该在单元测试中使用@Autowired@SpringBootTest吗?

2 个答案:

答案 0 :(得分:3)

不。 unit 测试用于隔离测试单个组件。在bean中使用构造函数注入使您可以非常简单地调用new SomeService(myMock),而无需Spring。

编写 component functional 测试(测试您的应用程序,但不将其连接到外部服务以进行完整的集成测试,仅模拟外部接口;这对事情有好处像MockMvc测试)非常适合@SpringBootTest,在这种情况下,您可能需要在Spring配置中创建模拟对象并将其自动连接到测试中,以便您进行操作。

答案 1 :(得分:0)

在TDD中进行测试应该是有帮助的,直接的,快速的,并保持最少的维护。否则,开发人员会感到烦恼,并尝试避免进行测试。
因此,我建议不要严格要求它是纯单元测试还是有点集成。选择最适合您的情况的测试范围,并使用适合此范围的技术功能。

如果您要进行“真实的”单元测试,请自己使用一个独立的方法,请不要使用DI。如果该方法做了有意义的事情,例如算法,计算,决策。在这里模拟数据源非常有用,以获得可预测的输入值。 您真正不需要的@SpringBootTest的缺点是启动时非常麻烦(取决于项目大小),这真令人讨厌。

如果方法调用依赖项上的功能,请使用CDI。 1)手动设置myService.service2 = new Service2()会给您留下同样不是由DI-Container处理的Service2,这可能需要您设置更多的依赖项... 2)Spring中的CDI测试很容易-那么为什么您会使用设置代码来夸大您的测试吗? 3)DI涉及的代理有时与简单实例的行为有所不同。

与@SpringBootTest相比,使用@ContextConfiguration(classes = {ServiceTest.class})可以更快地启动CDI。

请勿使用单元测试来测试粘合代码,因为它没有任何内在价值。这些测试很难理解(谁喜欢记录测试?),将需要大量模拟,并且经常会发生变化。与其他方法/类一起测试此类代码,即使这意味着您仅对代码的这些部分进行集成测试。