通用高层

通过学习的春天课程:

>>看看课程

1.概述

当我们的软件依赖于系统资源(如环境变量、系统属性)或使用过程级操作时,就很难对它进行测试system . exit

Java没有提供设置环境变量的直接方法,我们在一个测试中设置的值可能会影响另一个测试的执行。类似地,我们可能会发现自己避免为可能执行system . exit因为它有可能会中止测试。

系统规则和系统Lambda库是这些问题的早期解决方案。在本教程中,我们将研究System Lambda的一个新分支系统存根,它提供了JUnit 5的选择。

2.为什么系统存根?

2.1.系统Lambda不是一个JUnit插件

最初的系统规则库只能在JUnit 4中使用。它仍然可以用于JUnit古董在JUnit 5下,但这需要继续创建JUnit 4测试。库的创建者生成了一个测试框架未知版本,称为系统λ,用于每个测试方法中:

@Test void aSingleSystemLambda()抛出异常{restoreSystemProperties(() ->{系统。setProperty(“log_dir”、“测试/资源”);assertequal(“测试/资源”,System.getProperty (log_dir "));});//这里有更多的测试代码

测试代码被表示为lambda,传递给设置必要存根的方法。在将控制返回给测试方法的其余部分之前进行清理。

虽然这种方法在某些情况下效果很好,但也有一些缺点。

2.2.避免额外的代码

System Lambda方法的好处在于,在其工厂类中有一些用于执行特定类型测试的通用方法。然而,当我们想要在许多测试用例中使用它时,这会导致一些代码膨胀。

首先,即使测试代码本身没有抛出checked异常,包装器方法也会抛出,因此所有方法都将获得a抛出异常.其次,在多个测试中设置相同的规则需要代码重复。每个测试都需要独立地执行相同的配置。

然而,当我们试图一次设置多个工具时,这种方法最麻烦的方面就出现了。假设我们想设置一些环境变量和系统属性。在测试代码开始之前,我们需要两级嵌套:

@Test void multipleSystemLambdas()引发异常{restoreSystemProperties(()->{withEnvironmentVariable(“URL”)和//www.soft30t.comexecute金宝搏188体育(()->{System.setProperty(“log_dir”,“test/resources”);assertEquals(“test/resources”,System.getProperty(“log_dir”);assertEquals(“//www.soft30t.com,System.getenv(“URL”);};})

这就是JUnit插件或扩展可以帮助我们减少测试中所需代码量的地方。

2.3. 使用较少的样板

我们应该期望能够用最少的样板文件来编写测试:

@SystemStub private EnvironmentVariables EnvironmentVariables =…;@SystemStub private SystemProperties restoreSystemProperties;@Test void multiplesystemstub () {System. systemstbs ();setProperty(“log_dir”、“测试/资源”);assertequal(“测试/资源”,System.getProperty (log_dir "));assertequal (" https://www金宝搏188体育.baeldung.com " System.getenv(“地址”));}

该方法由SystemStubsJUnit 5扩展,允许用更少的代码编写测试。

2.4.测试生命周期钩子

当唯一可用的工具是execute-around模式,不可能将存根行为钩到测试生命周期的所有部分。当试图将它与其他JUnit扩展组合时,这尤其具有挑战性,例如@SpringBootTest

如果我们想围绕Spring启动测试设置一些环境变量,那么我们就无法将整个测试生态系统合理地嵌入到单个测试方法中。我们需要一种方法来激活测试套件周围的测试设置。

对于System Lambda所采用的方法来说,这是不可能的,这也是创建System stub的主要原因之一。

2.5.鼓励动态属性

用于设置系统属性的其他框架,例如JUnit先锋,强调编译时已知的配置。在现代测试中,我们可能使用测试容器Wiremock,我们需要在这些工具启动后基于随机运行时设置设置我们的系统属性。这与一个可以在整个测试生命周期中使用的测试库一起工作效果最好。

2.6。更多的可配置性

有现成的测试食谱很有好处,比如catchSystemExit,它封装测试代码以完成单个工作。然而,这依赖于测试库开发人员提供我们可能需要的每个配置选项的变化。

按组合进行配置更加灵活,是新系统存根实现的一大部分。

然而,系统存根支持来自System Lambda的原始测试构造为了向后兼容。此外,它还提供了一个新的JUnit 5扩展、一组JUnit 4规则和更多配置选项。虽然它是基于原始代码,但它已经被大量重构和模块化,以提供更丰富的功能集。

让我们了解更多。金宝搏官网188be

3.开始

3.1. 依赖关系

JUnit5扩展需要一个合理的最新版本JUnit 5

<依赖> < groupId > org.junit。木星 junit-jupiter 5.6.2 test 

把所有的加起来系统存根的库依赖项pom.xml

<!>  uk.org.webcompere system- stub- core 1.1.0 test    uk.org.webcompere system- stub- junit4 1.1.0 test    uk.org.webcompere system-stubs-jupiter 1.1.0 test 

我们应该注意到,我们只需要导入我们正在使用的测试框架所需要的数量。实际上,后两者都包含核心依赖关系。

现在,让我们编写第一个测试。

3.2. JUnit4环境变量

我们可以通过声明JUnit 4来控制环境变量@Rule类型测试类中的注释字段EnvironmentVariablesRule. 当我们的测试运行时,JUnit 4将激活它,并允许我们在测试中设置环境变量:

@Rule public EnvironmentVariablesRule EnvironmentVariablesRule = new EnvironmentVariablesRule();@Test public void givenenvironmentcanbemodified_whensetenenvironmentment_thenitisset(){环境变量规则。设置(“ENV”、“value1”);为了(System.getenv(“ENV”)).isEqualTo(“value1”);}

在实践中,我们可能更喜欢在a中设置环境变量值@Before方法,以便可以在所有测试之间共享设置:

@Before public void Before(){environmentVariablesRule.set(“ENV”,“value1”).set(“ENV2”,“value2”);}

这里我们应该注意使用fluent方法,这使得设置多个值变得很容易方法链

的构造函数也可以使用EnvironmentVariablesRule提供建筑价值的目的:

@Rule public EnvironmentVariablesRule EnvironmentVariablesRule = new EnvironmentVariablesRule("ENV", "value1", "ENV2", "value2");

构造函数有几个重载,允许以不同的形式提供变量。上面的例子允许使用任意数量的名称-值对可变参数

每个System stub JUnit 4规则都是一个核心存根对象的子类。也可以在整个测试类的生命周期中使用@ClassRule注释在一个静态字段,这将导致它们在第一次测试之前被激活,然后在最后一次测试之后被清除。

3.3.JUnit 5环境变量

在JUnit 5测试中使用System stub对象之前,必须将扩展添加到测试类中:

@ExtendWith(SystemStubsExtension.class)类EnvironmentVariablesJUnit5{//测试}

然后,我们可以在测试类中创建一个字段,以便JUnit 5为我们管理。我们用@系统存根所以扩展知道去激活它:

@SystemStub私有环境变量;

扩展将只管理标记为@系统存根,如果我们愿意,它允许我们在测试中手动使用其他System stub对象。

这里,我们没有提供存根对象的任何构造。扩展为我们构造了一个,方式与5扩展构造模拟。

现在,我们可以使用这个对象来帮助我们在一个测试中设置环境变量:

@Test void givenEnvironment可以在设置环境时修改它({Environment Variables.set(“ENV”,“value1”);assertThat(System.getenv(“ENV”))。isEqualTo(“value1”);}

如果我们想从测试方法外部提供应用于所有测试的环境变量,我们可以在@BeforeEach方法或可以使用的构造函数EnvironmentVariables设定我们的价值观:

@SystemStub private EnvironmentVariables EnvironmentVariables = new EnvironmentVariables("ENV", "value1");

EnvironmentVariablesRule构造函数有几个重载,允许我们以多种方式设置所需的变量。我们也可以用the方法流利地设置值,如果我们喜欢:

@SystemStub private EnvironmentVariables EnvironmentVariables = new EnvironmentVariables() .set("ENV", "value1") .set("ENV2", "value2");

我们也可以做我们的田地静态让他们作为。的一部分来管理@BeforeAll/@AfterAll生命周期。

3.4. JUnit5参数注入

当我们在所有测试中使用存根对象时,将存根对象放置在字段中是很有用的,但我们可能更愿意只在选定的测试中使用它们。这可以通过JUnit 5参数注入实现:

@Test void givenEnvironmentCanBeModified(EnvironmentVariables EnvironmentVariables){环境变量。设置(“ENV”、“value1”);为了(System.getenv(“ENV”)).isEqualTo(“value1”);}

在这种情况下EnvironmentVariables对象使用其默认构造函数为我们构造,允许我们在单个测试中使用它。对象也已被激活,以便它在运行时环境上操作。考试结束后会整理好。

所有System stub对象都有一个默认构造函数,并且能够在运行时重新配置。我们可以在测试中注入我们需要的任何数量。

3.5.Execute-Around环境变量

用于创建存根的原始System Lambda facade方法也可以通过SystemStubs类。在内部,它们是通过创建存根对象的实例实现的。有时,从recipe返回的对象是一个存根对象,用于进一步配置和使用:

/ /使用环境变量withEnvironmentVariable("ENV3", "val") .execute(() -> {assertThat(System.getenv("ENV3")).isEqualTo("val");});

在幕后,withEnvironmentVariable这相当于:

返回新EnvironmentVariables()。设置(“ENV3”、“val”);

执行方法对所有人来说都是通用的SystemStub对象。它设置由对象定义的存根,然后执行传入的lambda。之后,它整理并将控制权交还给周围的测试。

如果测试代码返回一个值,那么该值可以由执行

String extracted = new environments variables ("PROXY", "none") .execute(() -> System.getenv("PROXY"));为了(提取).isEqualTo(“没有”);

当我们正在测试的代码需要访问环境设置来构造某些东西时,这是非常有用的。它通常用于测试AWS Lambda处理程序之类的东西,通常通过环境变量进行配置。

这种模式用于偶尔测试的优点是,我们必须明确地设置存根,只有在需要的地方。因此,它可以更加精确和可见。但是,它不允许我们在测试之间共享设置,而且可能会比较冗长。

3.6。多个系统存根

我们已经看到JUnit 4和JUnit 5插件是如何为我们构造和激活存根对象的。如果有多个存根,它们将由框架代码适当地设置和拆除。

但是,当我们为executearound模式构造存根对象时,我们需要我们的测试代码在它们里面运行。

可以使用/执行方法。它们通过从多个stubing对象创建一个组合来工作,这些stubing对象与单个stubing对象一起使用执行

使用(新环境变量(“FOO”、“bar”)、新系统属性(“prop”、“val”).execute(()->{assertThat(System.getenv(“FOO”)).isEqualTo(“bar”);assertThat(System.getProperty(“prop”).isEqualTo(“val”)});

现在我们已经了解了使用System Stubs对象的一般形式,包括有JUnit框架支持和没有JUnit框架支持,让我们看看库的其余功能。

4.系统属性

我们可以打电话System.setProperty在Java的任何时候。但是,这样做有将设置从一个测试泄露到另一个测试的风险。的主要目的系统属性存根是在测试完成后将系统属性恢复到原来的设置。然而,对于普通的设置代码来说,在测试开始之前定义应该使用哪些系统属性也是有用的。

4.1. JUnit4系统属性

通过向JUnit4测试类添加规则,我们可以将每个测试与任何测试隔离开来System.setProperty在其他测试方法中调用。我们也可以通过构造函数提供一些前置属性:

@Rule public SystemPropertiesRule systemProperties = new SystemPropertiesRule("db. properties ");连接”、“假”);

有了这个对象,我们还可以在JUnit中设置一些附加属性@Before方法:

@Before public void before() {systemProperties.set("before. ");道具”、“前”);}

我们也可以用the方法在测试或使用的主体中System.setProperty如果我们的愿望。我们必须只使用在创建SystemPropertiesRule,或在@Before方法,因为它将设置存储在规则中,以便稍后应用。

4.2.JUnit 5系统属性

我们有两个使用系统属性对象。我们可能希望在每个测试用例之后重置系统属性,或者我们可能希望在中心位置为每个测试用例准备一些通用的系统属性。

恢复系统属性需要我们添加JUnit5扩展和系统属性字段到我们的测试类:

@extendedwith(SystemStubsExtension.class)类RestoreSystemProperties{@SystemStub private SystemProperties SystemProperties;}

现在,每个测试都会在测试结束后清理它所更改的任何系统属性。

我们也可以通过参数注入对选定的测试这样做:

@Test void willRestorePropertiesAfter(SystemProperties SystemProperties) {}

如果我们想要在测试中设置属性,那么我们可以在构造中分配这些属性系统属性物体或使用@BeforeEach方法:

@ExtendWith(SystemStubsExtension.class)类SetSomeSystemProperties {@SystemStub私有SystemProperties;@BeforeEach void before(){系统属性。设置(“beforeProperty”,“之前”);} }

再次,让我们注意到JUnit5测试需要用@ExtendWith (SystemStubsExtension.class)。如果我们不提供刚出现的语句在初始化列表中。

4.3.Execute Around的系统属性

SystemStubs类提供了一个恢复系统属性方法以允许我们在还原属性的情况下运行测试代码:

restoresystemproperty(()->{//test code System.setProperty(“unrestored”,“true”);});assertThat(System.getProperty(“unrestored”).isNull();

它接受一个不返回任何值的lambda。如果我们希望使用通用的设置函数来创建属性,可以从测试方法中获取返回值,或者组合使用系统属性与其他存根通过/执行,则可以显式创建对象:

String result = new SystemProperties() .execute(() -> {System. properties ();setProperty(“未”,“真正的”);返回“效果”;});为了(结果)。isEqualTo(“作品”);为了(System.getProperty(“未”)).isNull ();

4.4。属性文件

这两个系统属性EnvironmentVariables对象可以由地图.这允许Java的属性对象,作为系统属性或环境变量的源提供。

的内部有帮助器方法财产来源类,用于从文件或资源加载Java属性。这些属性文件是名称/值对:

name 金宝搏188体育= = 1.0 baeldung版本

我们可以从资源加载test.properties通过使用fromResource功能:

SystemProperties SystemProperties=新的系统属性(PropertySource.fromResource(“test.properties”);

中有类似的方便方法财产来源其他来源,例如fromFilefromInputStream

5.系统输出和系统错误

当我们的应用程序写入系统输出,这很难测试。这有时可以通过使用一个接口作为输出目标并在测试时模拟它来解决:

interface LogOutput {void write(String line);} class Component{私有LogOutput日志;Public void method(){日志。写(“输出”);} }

像这样的技巧很好用5模仿,但如果不是必需的我们可以设陷阱system . out本身。

5.1.JUnit 4SystemOutRuleSystemErrRule

捕获输出到system . out在JUnit 4测试中,我们添加SystemOutRule

@Rule public SystemOutRule SystemOutRule = new SystemOutRule();

在此之后,任何输出system . out可在测试中读出:

System.out.println(“第1行”);System.out.println(“第2行”);资产(systemOutRule.getLines())。包含实际的(“第1行”、“第2行”);

我们可以选择文本的格式。上面的例子使用了流<字符串>所提供的getLines.我们也可以选择获取整个文本块:

为了(systemOutRule.getText ()) .startsWith(“line1”);

但是,我们应该注意到该文本将具有不同平台的换行符。我们可以用\ n在每个平台上使用标准化形式:

为了(systemOutRule.getLinesNormalized ()) .isEqualTo(“line1 \ nline2 \ n”);

SystemErrRule对我来说也是如此System.err作为它的system . out对应:

@Rule public systememerrrule systememerrrule = new systememerrrule ();@Test public void whencodewritestosystemerr_itcaneread () {System.err.println("line1");System.err.println(“么”);为了(systemErrRule.getLines ()) .containsExactly(“line1”、“么”);}

还有一个SystemErrAndOutRule类,这两者都有system . outSystem.err同时进入单个缓冲区。

5.2。JUnit 5例

与其他System stub对象一样,我们只需要声明一个类型的字段或参数SystemOutSystemErr. 这将为我们提供输出的捕获:

@SystemStub私有SystemOut SystemOut@SystemStub私有SystemErr SystemErr@当WriteToOut\u thenit可以被设置为空时测试无效({System.out.println(“to out”);System.err.println(“to err”);assertThat(systemOut.getLines())。ContainesExactly(“to out”);assertThat(systemErr.getLines())。ContainesExactly(“to err”);}

我们也可以用theSystemErrAndOut类将这两组输出定向到同一缓冲区。

5.3。Execute-Around例子

SystemStubsFacade提供了一些函数来点击输出并将其作为返回字符串

@Test void givenTapOutput_thenGetOutput()抛出异常{String output=tapSystemOutNormalized(()->{System.out.println(“a”);System.out.println(“b”);});assertThat(output.isEqualTo(“a\nb\n”);}

我们应该注意到,这些方法并不像原始对象本身那样提供丰富的接口。输出的捕获不能很容易地与其他存根相结合,例如设置环境变量。

但是,SystemOutSystemErr,中SystemErrAndOut对象可以直接使用。例如,我们可以将它们与一些系统属性

SystemOut = new SystemOut();SystemProperties = new SystemProperties("a", "!");使用(systemOut, systemProperties) .execute(()println("a: " + System.getProperty("a"));});为了(systemOut.getLines())。containsExactly(: !”);

5.4。静音

有时,我们的目标不是捕获输出,而是防止它弄乱测试运行日志。我们可以使用静音系统输出互斥系统错误功能:

muteSystemOut(() ->{系统输出。println(“输出”);});

我们可以通过JUnit4在所有测试中实现相同的功能SystemOutRule

@Rule public SystemOutRule SystemOutRule=new SystemOutRule(new NoopStream());

在JUnit 5中,我们可以使用相同的技术:

@SystemStub private SystemOut SystemOut = new SystemOut(new NoopStream());

5.5。定制

正如我们所看到的,有几种用于拦截输出的变体。它们在库中共享一个公共基类。为方便起见,有几个助手方法和类型,比如SystemErrAndOut,帮助做普通的事情。然而,库本身很容易定制。

我们可以为捕获输出提供自己的目标,作为输出.我们已经看过了输出TapStream在第一个例子中使用。暗流用于静音。我们也有DisallowWriteStream如果有东西写到它,就会抛出一个错误:

//抛出异常:new SystemOut(new DisallowWriteStream()) .execute(() -> System.out.println("boo"));

6.模拟系统

我们可能有一个应用程序可以读取stdin.测试这可能涉及到将算法提取到一个函数中,该函数从任意InputStream然后给它一个预先准备好的输入流。一般来说,模块化代码更好,所以这是一个很好的模式。

然而,如果我们只测试核心功能,我们就会失去对代码的测试覆盖系统作为源头。

在任何情况下,构建我们自己的流都很不方便。幸运的是,System stub有解决所有这些问题的方案。

6.1.测试输入流

系统存根提供了一个家庭AltInputStream类作为对象中读取的任何代码的替代输入InputStream

LinesAltStream testInput = new LinesAltStream("line1", "line2");scan scan = new scan (testInput);为了(scanner.nextLine ()) .isEqualTo(“line1”);

在这个例子中,我们使用了一个字符串数组来构造LinesAltStream,但我们可以从a提供输入流<字符串>,允许它用于任何文本数据源而不必一次将所有数据加载到内存中。

6.2。JUnit 4的例子

属性可以在JUnit 4测试中提供输入行SystemInRule

@Rule public SystemInRule SystemInRule = new SystemInRule("line1", "line2", "line3");

然后,测试代码可以从其中读取这个输入系统

@Test public void givenInput_canReadFirstLine() {assertThat(new Scanner(System.in).nextLine()) .isEqualTo("line1");}

6.3。JUnit 5例

对于JUnit 5测试,我们创建一个与其他人字段:

@SystemStub private SystemIn SystemIn=新SystemIn(“第1行”、“第2行”、“第3行”);

然后我们的测试就开始了系统提供这些行作为输入。

6.4。Execute-Around例子

SystemStubs门面提供withTextFromSystemIn作为工厂方法创建与其他人对象,以便与其一起使用执行方法:

使用textfromsystemin ("line1", "line2", "line3") .execute(() -> {assertThat(new Scanner(System.in).nextLine()) .isEqualTo("line1");});

6.5. 定制

更多的功能可以添加到与其他人对象在构造时或在测试中运行时。

我们可以打电话andExceptionThrownOnInputEnd,它导致阅读系统在耗尽文本时抛出异常。这可以模拟对文件的中断读取。

我们还可以将输入流设置为来自任意InputStream喜欢FileInputStream,通过使用setInputStream.我们也有LinesAltStreamTextAltStream,对输入文本进行操作。

7.模拟系统。退出

如前所述,如果我们的代码可以调用system . exit,它可能导致危险且难以调试的测试故障。我们的目标之一是存根system . exit是偶然调用一个可跟踪错误。另一个动机是测试有意退出软件。

7.1。JUnit 4的例子

让我们加入系统出口作为一种安全措施来防止任何system . exit停止JVM:

@Rule public SystemExitRule SystemExitRule = new SystemExitRule();

然而,我们可能还想看看是否使用了正确的退出代码.为此,我们需要断言代码抛出AbortExecutionException这是系统存根发出的信号system . exit被称为。

@Test public void whenExit_thenExitCodeIsAvailable() {assertThatThrownBy(() -> {System.exit(123);}) .isInstanceOf (AbortExecutionException.class);为了(systemExitRule.getExitCode ()) .isEqualTo (123);}

在本例中,我们使用了斯洛恩比资产AssertJ要捕获和检查异常信号出口发生。然后我们研究了getExitCode系统出口断言退出代码。

7.2. JUnit5示例

对于JUnit 5测试,我们声明@系统存根字段:

@SystemStub private SystemExit;

然后我们使用SystemExit以同样的方式系统出口在JUnit 4中。考虑到系统出口类是的子类SystemExit,它们有相同的界面。

7.3。Execute-Around例子

SystemStubs类提供了catchSystemExit,它在内部使用SystemExit执行功能:

int exitCode = catchSystemExit(() -> {System.exit(123);});为了(exitCode) .isEqualTo (123);

与JUnit插件示例相比,此代码没有抛出异常以指示系统退出。相反,它捕获错误并记录退出代码。使用facade方法,它将返回退出代码。

当我们使用执行方法,将捕获退出,并在SystemExit对象。然后我们可以打电话getExitCode获取退出代码,或无效的如果没有。

8.JUnit5中的自定义测试资源

JUnit 4已经提供了一个创建测试规则的简单结构就像在系统存根中使用的一样。如果我们想为某些资源创建一个新的测试规则,通过设置和拆卸,我们可以将其子类化外部资源并提供覆盖之前方法。

JUnit 5具有更复杂的资源管理模式。对于简单的用例,可以使用System stub库作为起点。的SystemStubsExtension作用于任何满足TestResource接口。

8.1。创建一个TestResource

我们可以创建的子类TestResource然后使用自定义对象,就像我们使用System stub对象一样。需要注意的是,如果要使用字段和参数的自动创建,需要提供默认构造函数。

假设我们想打开一个数据库连接进行一些测试,然后关闭它:

public class FakeDatabaseTestResource implements TestResource{//假设这是一个数据库连接private String databaseConnection = "closed";@Override public void setup() throws Exception {databaseConnection = "open";} @Override public void teardown() throws Exception {databaseConnection = "closed";} public String getDatabaseConnection() {return databaseConnection;} }

我们使用databaseConnection字符串作为资源(如数据库连接)的说明。中修改资源的状态设置拆卸方法。

8.2.Execute-Around是内置的

现在让我们试着用execute-around模式来使用它:

FakeDatabaseTestResource = new FakeDatabaseTestResource();为了(fake.getDatabaseConnection ()) .isEqualTo(“关闭”);false .execute(() -> {assertThat(false . getdatabaseconnection ()).isEqualTo("open");});

我们可以看到TestResource接口赋予了它执行其他对象的能力。

8.3. 风俗TestResource在JUnit 5测试

我们也可以在JUnit 5测试中使用它:

@使用(SystemStubsExtension.class)类FakeDatabaseJUnitTest{@Test void useFakeDatabase(FakeDatabaseTestResource fakeDatabase){assertThat(fakeDatabase.getDatabaseConnection()).isEqualTo(“打开”);}

所以,创建额外的测试对象很容易遵循系统存根设计。

9.JUnit 5 Spring测试的环境和属性覆盖

为Spring测试设置环境变量可能很困难。我们可能会编写自定义规则用于集成测试,以便为Spring设置一些系统属性。

我们也可以使用ApplicationContextInitializer类插入到Spring上下文中,为测试提供额外的属性。

由于许多Spring应用程序是由系统属性或环境变量覆盖控制的,因此使用system stub在外部测试中设置它们可能更容易,而Spring测试作为内部类运行。

有一个完整的示例在系统存根文档中提供。我们从创建一个外部类开始:

@ExtendWith(SystemStubsExtension.class) public class SpringAppWithDynamicPropertiesTest{//在Spring启动之前设置环境@SystemStub私有静态环境变量环境变量;}

在这个例子中,@SystemStub字段是静态并在@BeforeAll方法:

@BeforeAll static void beforeAll() {String baseUrl =…;environmentVariables。集("SERVER_URL", baseUrl); }

测试生命周期中的这一点允许在Spring测试运行之前创建一些全局资源并将其应用到运行环境中。

然后,我们可以把Spring测试变成@Nested类。这使得它只在父类建立时运行:

@嵌套@SpringBootTest(class = {RestApi.class, App.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)类InnerSpringTest {@LocalServerPort private int serverPort;//测试方法}

Spring上下文是根据@SystemStub对象在外部类中。

这种技术还允许我们控制依赖于在Spring Beans之后运行的系统属性或环境变量状态的任何其他库的配置。

这可以让我们挂钩到测试生命周期中,以修改代理设置或HTTP连接池参数等内容在Spring测试运行之前。

10.结论

在本文中,我们讨论了能够模拟系统资源的重要性,以及系统存根如何允许通过JUnit4和JUnit5插件以最少的代码重复进行复杂的存根配置。

我们看到了如何在测试中提供和隔离环境变量和系统属性。然后我们研究了如何在标准流上捕获输出和控制输入。我们还研究了对的捕获和断言调用system . exit

最后,我们讨论了如何创建自定义测试资源以及如何在Spring中使用System stub。

与往常一样,示例的完整源代码是可用的在GitHub

通用的底部

通过学习的春天课程:

>>看看课程
Junit页脚横幅
这篇文章的评论已经关闭!