我正在从事Spring Boot项目。 我正在基于“ TDD”编写“单元测试”代码,这有点困难。
@SpringBootTest加载了所有BEAN,这导致更长的测试时间。
所以我使用了@SpringBootTest的类名称。
我正常完成了测试,但是我不确定使用@ContextConfiguration与使用@Import之间的区别。
所有三个选项均正常运行。我想知道哪种选择是最好的。
"email: "notauser@test.com"
答案 0 :(得分:4)
我认为如果您打算进行适当的单元测试,那么给出的所有3个选项都是不好的。 单元测试必须非常快,您应该能够在一秒钟左右的时间里运行数百个(当然,这取决于硬件,但是您知道了)。 因此,一旦您说出“我为每项测试开始测试”,它就不再是单元测试了。 每次测试都要从弹簧开始,这是非常昂贵的操作。
有趣的是,您的CoffeeService
代码是以完全可测试的方式编写的:只需使用Mockito之类的库来模拟存储库类,然后就可以毫无问题地测试服务逻辑。
您将不需要任何弹簧滑块,任何弹簧注释。您还将看到这些测试的运行速度更快。
class MyServiceTest {
@Test
public void test_my_service_get_coffee_logic() {
// setup
CoffeeRepository repo = Mockito.mock(CoffeeRepository.class);
Mockito.when(repo.findByName("mocha")).thenReturn("coffeeFound");
CoffeeService underTest = new CoffeeService(repo);
// when:
String actualCoffee = underTest.getCoffee("mocha");
// then:
assertEquals(actualCoffee, "coffeeFound");
}
}
现在有关弹簧测试库
您可以将其视为测试代码的一种方法,该代码需要与其他组件进行某些互连,并且很难模拟所有内容。它是同一JVM内的一种集成测试。 您提供的所有方式都在运行应用程序上下文,这实际上是一个非常复杂的事情,在youtube上有很多关于应用程序上下文启动期间实际发生情况的会话-尽管超出了问题的范围,问题是执行上下文启动需要时间
@SpringBootTest
更进一步,尝试模仿Spring Boot框架添加的用于创建上下文的过程:根据包结构决定要扫描的内容,从预定义的位置加载外部配置(可选),运行自动配置启动器,依此类推。
现在,可能会加载应用程序中所有bean的应用程序上下文可能非常大,并且对于某些测试来说,它不是必需的。 通常取决于测试的目的
例如,如果您测试其余控制器(已正确放置所有批注),则可能不需要启动数据库连接。
您介绍的所有方式都会过滤应该运行的内容,要加载和注入的bean。
通常,这些限制适用于“层”而不是单个bean(层=其余层,数据层等)。
第二种方法和第三种方法实际上是相同的,它们是“过滤”应用程序上下文的方法,仅保留必要的bean。
更新:
由于您已经完成了方法的性能比较:
单元测试=非常快速的测试,其目的是验证您编写的代码(或者当然是您的一位同事) 因此,如果您运行Spring,它会自动意味着相对缓慢的测试。因此,回答您的问题
是否使用@ContextConfiguration可以作为“单元测试”
不,不能,这是一个集成测试,在春季仅运行一个类。
通常,我们不会只使用Spring Framework运行一个类。如果只想测试一个类(一个单元)的代码,在spring容器中运行它有什么好处?是的,在某些情况下,它可能只有几节课,但不能是几十个或数百个。
如果您在spring上运行一个类,那么无论如何,您都必须模拟其所有依赖项,可以通过模仿来完成...
现在关于您的问题
@ContextConfiguration与@SpringBootTest的技术差异。
@SpringBootTest
仅在您具有Spring Boot应用程序时才相关。该框架在幕后使用Spring,但总的来说,它附带了许多有关如何编写应用程序“基础结构”的预定义配方/实践:
- 配置管理,
-包装结构,
-可插拔性
-记录
-数据库集成等。
因此,Spring Boot建立了定义明确的流程来处理所有上述项目,如果您想启动将模拟Spring Boot应用程序的测试,则可以使用@SpringBootTest
批注。否则(或者如果您只有弹簧驱动的应用程序而没有弹簧靴)-根本不要使用它。
@ContextConfiguration
是完全不同的东西。它只是说您想在Spring驱动的应用程序中使用什么bean(它也可以在spring boot中使用)
“单元测试”是使用@ContextConfiguration的正确方法吗?还是不?
正如我所说-所有与弹簧测试有关的东西仅用于集成测试,所以不,这是在单元测试中使用的错误方法。对于单元测试,应该使用完全不使用spring的东西(例如模拟的mockito和没有springRunner的常规junit测试)。
答案 1 :(得分:0)
就像@MarkBramnik一样,如果您打算编写单元测试,则必须模拟使用您正在测试的特定组件的其他组件。 如果要编写模拟应用程序过程的集成测试,建议使用@SpringBootTest。 在单元测试中@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ s转