</div> <button (click)="save()">Save</button> <button (click)="cancel()">Cancel</button> </div>
Tests that exercise the component need ...
这些供练习用的组件需要 ……
to wait until a hero arrives before elements appear in the DOM.
等获取到英雄之后才能让元素出现在 DOM 中。
a reference to the title text.
一个对标题文本的引用。
a reference to the name input box to inspect and set it.
一个对 name 输入框的引用,以便对它进行探查和修改。
references to the two buttons so they can click them.
引用两个按钮,以便点击它们。
spies for some of the component and router methods.
为组件和路由器的方法安插间谍。
Even a small form such as this one can produce a mess of tortured conditional setup and CSS element selection.
即使是像这样一个很小的表单,也能产生令人疯狂的错综复杂的条件设置和 CSS 元素选择。
Tame the complexity with a Page
class that handles access to component properties and encapsulates the logic that sets them.
可以使用 Page
类来征服这种复杂性。Page
类可以处理对组件属性的访问,并对设置这些属性的逻辑进行封装。
Here is such a Page
class for the hero-detail.component.spec.ts
下面是一个供 hero-detail.component.spec.ts
使用的 Page
类
Now the important hooks for component manipulation and inspection are neatly organized and accessible from an instance of Page
.
现在,用来操作和检查组件的重要钩子都被井然有序的组织起来了,可以通过 page
实例来使用它们。
A createComponent
method creates a page
object and fills in the blanks once the hero
arrives.
createComponent
方法创建 page
,在 hero
到来时,自动填补空白。
The HeroDetailComponent tests in an earlier section demonstrate how createComponent
and page
keep the tests short and on message. There are no distractions: no waiting for promises to resolve and no searching the DOM for element values to compare.
前面小节中的 HeroDetailComponent
测试示范了如何 createComponent
,而 page
让这些测试保持简短而富有表达力。 而且还不用分心:不用等待承诺被解析,不必在 DOM 中找出元素的值才能进行比较。
Here are a few more HeroDetailComponent
tests to reinforce the point.
还有更多的 HeroDetailComponent
测试可以证明这一点。
compileComponents()
linkYou can ignore this section if you only run tests with the CLI ng test
command because the CLI compiles the application before running the tests.
如果你只想使用 CLI 的 ng test
命令来运行测试,那么可以忽略这一节。
If you run tests in a non-CLI environment, the tests may fail with a message like this one:
如果你在非 CLI 环境中运行测试,这些测试可能会报错,错误信息如下:
The root of the problem is at least one of the components involved in the test specifies an external template or CSS file as the following version of the BannerComponent
does.
问题的根源在于这个测试中至少有一个组件引用了外部模板或外部 CSS 文件,就像下面这个 BannerComponent
所示:
The test fails when the TestBed
tries to create the component.
当 TestBed
视图创建组件时,这个测试失败了:
Recall that the app hasn't been compiled. So when you call createComponent()
, the TestBed
compiles implicitly.
回想一下,这个应用从未编译过。 所以当你调用 createComponent()
的时候,TestBed
就会进行隐式编译。
That's not a problem when the source code is in memory. But the BannerComponent
requires external files that the compile must read from the file system, an inherently asynchronous operation.
当它的源码都在内存中的时候,这样做没问题。 不过 BannerComponent
需要一些外部文件,编译时必须从文件系统中读取它,而这是一个天生的异步操作。
If the TestBed
were allowed to continue, the tests would run and fail mysteriously before the compiler could finished.
如果 TestBed
继续执行,这些测试就会继续运行,并在编译器完成这些异步工作之前导致莫名其妙的失败。
The preemptive error message tells you to compile explicitly with compileComponents()
.
这些错误信息告诉你要使用 compileComponents()
进行显式的编译。
compileComponents()
是异步的linkYou must call compileComponents()
within an asynchronous test function.
你必须在异步测试函数中调用 compileComponents()
。
If you neglect to make the test function async (e.g., forget to use async()
as described below), you'll see this error message
如果你忘了把测试函数标为异步的(比如忘了像稍后的代码中那样使用 async()
),就会看到下列错误。
A typical approach is to divide the setup logic into two separate beforeEach()
functions:
典型的做法是把准备逻辑拆成两个独立的 beforeEach()
函数:
An async beforeEach()
that compiles the components
异步的 beforeEach()
负责编译组件
A synchronous beforeEach()
that performs the remaining setup.
同步的 beforeEach()
负责执行其余的准备代码。
To follow this pattern, import the async()
helper with the other testing symbols.
要想使用这种模式,就要和其它符号一起从测试库中导入 async()
辅助函数。
beforeEach
linkWrite the first async beforeEach
like this.
像下面这样编写第一个异步的 beforeEach
。
The async()
helper function takes a parameterless function with the body of the setup.
async()
辅助函数接受一个无参函数,其内容是准备代码。
The TestBed.configureTestingModule()
method returns the TestBed
class so you can chain calls to other TestBed
static methods such as compileComponents()
.
TestBed.configureTestingModule()
方法返回 TestBed
类,所以你可以链式调用其它 TestBed
中的静态方法,比如 compileComponents()
。
In this example, the BannerComponent
is the only component to compile. Other examples configure the testing module with multiple components and may import application modules that hold yet more components. Any of them could be require external files.
在这个例子中,BannerComponent
是仅有的待编译组件。 其它例子中可能会使用多个组件来配置测试模块,并且可能引入某些具有其它组件的应用模块。 它们中的任何一个都可能需要外部文件。
The TestBed.compileComponents
method asynchronously compiles all components configured in the testing module.
TestBed.compileComponents
方法会异步编译测试模块中配置过的所有组件。
Do not re-configure the TestBed
after calling compileComponents()
.
在调用了 compileComponents()
之后就不能再重新配置 TestBed
了。
Calling compileComponents()
closes the current TestBed
instance to further configuration. You cannot call any more TestBed
configuration methods, not configureTestingModule()
nor any of the override...
methods. The TestBed
throws an error if you try.
调用 compileComponents()
会关闭当前的 TestBed
实例,不再允许进行配置。 你不能再调用任何 TestBed
中的配置方法,既不能调 configureTestingModule()
,也不能调用任何 override...
方法。如果你试图这么做,TestBed
就会抛出错误。
Make compileComponents()
the last step before calling TestBed.createComponent()
.
确保 compileComponents()
是调用 TestBed.createComponent()
之前的最后一步。
beforeEach
linkThe second, synchronous beforeEach()
contains the remaining setup steps, which include creating the component and querying for elements to inspect.
第二个同步 beforeEach()
的例子包含剩下的准备步骤, 包括创建组件和查询那些要检查的元素。
You can count on the test runner to wait for the first asynchronous beforeEach
to finish before calling the second.
测试运行器(runner)会先等待第一个异步 beforeEach
函数执行完再调用第二个。
You can consolidate the two beforeEach()
functions into a single, async beforeEach()
.
你可以把这两个 beforeEach()
函数重整成一个异步的 beforeEach()
。
The compileComponents()
method returns a promise so you can perform the synchronous setup tasks after compilation by moving the synchronous code into a then(...)
callback.
compileComponents()
方法返回一个承诺,所以你可以通过把同步代码移到 then(...)
回调中, 以便在编译完成之后 执行那些同步准备任务。
compileComponents()
是无害的linkThere's no harm in calling compileComponents()
when it's not required.
在不需要 compileComponents()
的时候调用它也不会有害处。
The component test file generated by the CLI calls compileComponents()
even though it is never required when running ng test
.
虽然在运行 ng test
时永远都不需要调用 compileComponents()
,但 CLI 生成的组件测试文件还是会调用它。
The tests in this guide only call compileComponents
when necessary.
但这篇指南中的这些测试只会在必要时才调用 compileComponents
。
imports
linkEarlier component tests configured the testing module with a few declarations
like this:
此前的组件测试程序使用了一些 declarations
来配置模块,就像这样:
The DashboardComponent
is simple. It needs no help. But more complex components often depend on other components, directives, pipes, and providers and these must be added to the testing module too.
DashbaordComponent
非常简单。它不需要帮助。 但是更加复杂的组件通常依赖其它组件、指令、管道和提供商, 所以这些必须也被添加到测试模块中。
Fortunately, the TestBed.configureTestingModule
parameter parallels the metadata passed to the @NgModule
decorator which means you can also specify providers
and imports
.
幸运的是,TestBed.configureTestingModule
参数与传入 @NgModule
装饰器的元数据一样,也就是所你也可以指定 providers
和 imports
.
The HeroDetailComponent
requires a lot of help despite its small size and simple construction. In addition to the support it receives from the default testing module CommonModule
, it needs:
虽然 HeroDetailComponent
很小,结构也很简单,但是它需要很多帮助。 除了从默认测试模块 CommonModule
中获得的支持,它还需要:
NgModel
and friends in the FormsModule
to enable two-way data binding.
FormsModule
里的 NgModel
和其它,来进行双向数据绑定
The TitleCasePipe
from the shared
folder.
shared
目录里的 TitleCasePipe
Router services (which these tests are stubbing).
一些路由器服务(测试程序将 stub 伪造它们)
Hero data access services (also stubbed).
英雄数据访问服务(同样被 stub 伪造了)
One approach is to configure the testing module from the individual pieces as in this example:
一种方法是在测试模块中一一配置,就像这样:
Notice that the beforeEach()
is asynchronous and calls TestBed.compileComponents
because the HeroDetailComponent
has an external template and css file.
注意,beforeEach()
是异步的,它调用 TestBed.compileComponents
是因为 HeroDetailComponent
有外部模板和 CSS 文件。
As explained in Calling compileComponents() above, these tests could be run in a non-CLI environment where Angular would have to compile them in the browser.
如前面的调用 compileComponents()
中所解释的那样,这些测试可以运行在非 CLI 环境下,那里 Angular 并不会在浏览器中编译它们。
Because many app components need the FormsModule
and the TitleCasePipe
, the developer created a SharedModule
to combine these and other frequently requested parts.
因为很多应用组件都需要 FormsModule
和 TitleCasePipe
,所以开发者创建了 SharedModule
来把它们及其它常用的部分组合在一起。
The test configuration can use the SharedModule
too as seen in this alternative setup:
这些测试配置也可以使用 SharedModule
,如下所示:
It's a bit tighter and smaller, with fewer import statements (not shown).
它的导入声明少一些(未显示),稍微干净一些,小一些。
The HeroDetailComponent
is part of the HeroModule
Feature Module that aggregates more of the interdependent pieces including the SharedModule
. Try a test configuration that imports the HeroModule
like this one:
HeroDetailComponent
是 HeroModule
这个特性模块的一部分,它聚合了更多相互依赖的片段,包括 SharedModule
。 试试下面这个导入了 HeroModule
的测试配置:
That's really crisp. Only the test doubles in the providers
remain. Even the HeroDetailComponent
declaration is gone.
这样特别清爽。只有 providers
里面的测试替身被保留。连 HeroDetailComponent
声明都消失了。
In fact, if you try to declare it, Angular will throw an error because HeroDetailComponent
is declared in both the HeroModule
and the DynamicTestModule
created by the TestBed
.
事实上,如果你试图声明它,Angular 就会抛出一个错误,因为 HeroDetailComponent
同时声明在了 HeroModule
和 TestBed
创建的 DynamicTestModule
中。
Importing the component's feature module can be the easiest way to configure tests when there are many mutual dependencies within the module and the module is small, as feature modules tend to be.
如果模块中有很多共同依赖,并且该模块很小(这也是特性模块的应有形态),那么直接导入组件的特性模块可以成为配置这些测试的简易方式。
The HeroDetailComponent
provides its own HeroDetailService
.
HeroDetailComponent
提供自己的 HeroDetailService
服务。
It's not possible to stub the component's HeroDetailService
in the providers
of the TestBed.configureTestingModule
. Those are providers for the testing module, not the component. They prepare the dependency injector at the fixture level.
在 TestBed.configureTestingModule
的 providers
中 stub 伪造组件的 HeroDetailService
是不可行的。 这些是测试模块的提供商,而非组件的。组件级别的供应商应该在fixture 级别准备的依赖注入器。
Angular creates the component with its own injector, which is a child of the fixture injector. It registers the component's providers (the HeroDetailService
in this case) with the child injector.
Angular 会使用自己的注入器来创建这些组件,这个注入器是夹具的注入器的子注入器。 它使用这个子注入器注册了该组件服务提供商(这里是 HeroDetailService
)。
A test cannot get to child injector services from the fixture injector. And TestBed.configureTestingModule
can't configure them either.
测试没办法从测试夹具的注入器中获取子注入器中的服务,而 TestBed.configureTestingModule
也没法配置它们。
Angular has been creating new instances of the real HeroDetailService
all along!
Angular 始终都在创建真实 HeroDetailService
的实例。
These tests could fail or timeout if the HeroDetailService
made its own XHR calls to a remote server. There might not be a remote server to call.
如果 HeroDetailService
向远程服务器发出自己的 XHR 请求,这些测试可能会失败或者超时。 这个远程服务器可能根本不存在。
Fortunately, the HeroDetailService
delegates responsibility for remote data access to an injected HeroService
.
幸运的是,HeroDetailService
将远程数据访问的责任交给了注入进来的 HeroService
。
The previous test configuration replaces the real HeroService
with a TestHeroService
that intercepts server requests and fakes their responses.
前面的测试配置使用 TestHeroService
替换了真实的 HeroService
,它拦截了发往服务器的请求,并伪造了服务器的响应。
What if you aren't so lucky. What if faking the HeroService
is hard? What if HeroDetailService
makes its own server requests?
如果你没有这么幸运怎么办?如果伪造 HeroService
很难怎么办?如果 HeroDetailService
自己发出服务器请求怎么办?
The TestBed.overrideComponent
method can replace the component's providers
with easy-to-manage test doubles as seen in the following setup variation:
TestBed.overrideComponent
方法可以将组件的 providers
替换为容易管理的测试替身,参见下面的变体准备代码:
Notice that TestBed.configureTestingModule
no longer provides a (fake) HeroService
because it's not needed.
注意,TestBed.configureTestingModule
不再提供(伪造的)HeroService
,因为并不需要。
overrideComponent
方法linkFocus on the overrideComponent
method.
注意这个 overrideComponent
方法。
It takes two arguments: the component type to override (HeroDetailComponent
) and an override metadata object. The override metadata object is a generic defined as follows:
它接受两个参数:要改写的组件类型(HeroDetailComponent
),以及用于改写的元数据对象。 用于改写的元数据对象是一个泛型,其定义如下:
A metadata override object can either add-and-remove elements in metadata properties or completely reset those properties. This example resets the component's providers
metadata.
元数据重载对象可以添加和删除元数据属性的项目,也可以彻底重设这些属性。 这个例子重新设置了组件的 providers
元数据。
The type parameter, T
, is the kind of metadata you'd pass to the @Component
decorator:
这个类型参数,T
,是你会传递给 @Component
装饰器的元数据的类型。
间谍桩
(HeroDetailServiceSpy
)linkThis example completely replaces the component's providers
array with a new array containing a HeroDetailServiceSpy
.
这个例子把组件的 providers
数组完全替换成了一个包含 HeroDetailServiceSpy
的新数组。
The HeroDetailServiceSpy
is a stubbed version of the real HeroDetailService
that fakes all necessary features of that service. It neither injects nor delegates to the lower level HeroService
so there's no need to provide a test double for that.
HeroDetailServiceSpy
是实际 HeroDetailService
服务的桩版本,它伪造了该服务的所有必要特性。 但它既不需要注入也不会委托给低层的 HeroService
服务,因此不用为 HeroService
提供测试替身。
The related HeroDetailComponent
tests will assert that methods of the HeroDetailService
were called by spying on the service methods. Accordingly, the stub implements its methods as spies:
通过对该服务的方法进行刺探,HeroDetailComponent
的关联测试将会对 HeroDetailService
是否被调用过进行断言。 因此,这个桩类会把它的方法实现为刺探方法:
Now the tests can control the component's hero directly by manipulating the spy-stub's testHero
and confirm that service methods were called.
现在,测试程序可以通过操控 stub 的 testHero
,直接控制组件的英雄,并确保服务的方法被调用过。
The TestBed.overrideComponent
method can be called multiple times for the same or different components. The TestBed
offers similar overrideDirective
, overrideModule
, and overridePipe
methods for digging into and replacing parts of these other classes.
TestBed.overrideComponent
方法可以在相同或不同的组件中被反复调用。 TestBed
还提供了类似的 overrideDirective
、overrideModule
和 overridePipe
方法,用来深入并重载这些其它类的部件。
Explore the options and combinations on your own.
自己探索这些选项和组合。
An attribute directive modifies the behavior of an element, component or another directive. Its name reflects the way the directive is applied: as an attribute on a host element.
属性指令修改元素、组件和其它指令的行为。正如它们的名字所示,它们是作为宿主元素的属性来被使用的。
The sample application's HighlightDirective
sets the background color of an element based on either a data bound color or a default color (lightgray). It also sets a custom property of the element (customProperty
) to true
for no reason other than to show that it can.
本例子应用的 HighlightDirective
使用数据绑定的颜色或者默认颜色来设置元素的背景色。 它同时设置元素的 customProperty
属性为 true
,这里仅仅是为了显示它能这么做而已,并无其它原因。
It's used throughout the application, perhaps most simply in the AboutComponent
:
它的使用贯穿整个应用,也许最简单的使用在 AboutComponent
里:
Testing the specific use of the HighlightDirective
within the AboutComponent
requires only the techniques explored above (in particular the "Shallow test" approach).
要想在 AboutComponent
中测试 HighlightDirective
的具体用法,只要使用在“浅层测试”部分用过的技术即可。
However, testing a single use case is unlikely to explore the full range of a directive's capabilities. Finding and testing all components that use the directive is tedious, brittle, and almost as unlikely to afford full coverage.
但是,测试单一的用例一般无法探索该指令的全部能力。 查找和测试所有使用该指令的组件非常繁琐和脆弱,并且通常无法覆盖所有组件。
Class-only tests might be helpful, but attribute directives like this one tend to manipulate the DOM. Isolated unit tests don't touch the DOM and, therefore, do not inspire confidence in the directive's efficacy.
只针对类的测试可能很有用, 但是像这个一样的属性型指令肯定要操纵 DOM。 隔离出的单元测试不能接触 DOM,因此也就没办法证明该指令的有效性。
A better solution is to create an artificial test component that demonstrates all ways to apply the directive.
更好的方法是创建一个能展示该指令所有用法的人造测试组件。
The <input>
case binds the HighlightDirective
to the name of a color value in the input box. The initial value is the word "cyan" which should be the background color of the input box.
<input>
用例将 HighlightDirective
绑定到输入框里输入的颜色名字。 初始只是单词“cyan”,所以输入框的背景色应该是 cyan。
Here are some tests of this component:
下面是一些该组件的测试程序:
A few techniques are noteworthy:
一些技巧值得注意:
The By.directive
predicate is a great way to get the elements that have this directive when their element types are unknown.
当已知元素类型时,By.directive
是一种获取拥有这个指令的元素的好方法。
The :not
pseudo-class in By.css('h2:not([highlight])')
helps find <h2>
elements that do not have the directive. By.css('*:not([highlight])')
finds any element that does not have the directive.
By.css('h2:not([highlight])')
里的:not
伪类(pseudo-class)帮助查找不带该指令的 <h2>
元素。By.css('*:not([highlight])')
查找所有不带该指令的元素。
DebugElement.styles
affords access to element styles even in the absence of a real browser, thanks to the DebugElement
abstraction. But feel free to exploit the nativeElement
when that seems easier or more clear than the abstraction.
DebugElement.styles
甚至不用借助真实的浏览器也可以访问元素的样式,感谢 DebugElement
提供的这层抽象! 但是如果直接使用 nativeElement
会比这层抽象更简单、更清晰,也可以放心大胆的使用它。
Angular adds a directive to the injector of the element to which it is applied. The test for the default color uses the injector of the second <h2>
to get its HighlightDirective
instance and its defaultColor
.
Angular 将指令添加到它的元素的注入器中。默认颜色的测试程序使用第二个 <h2>
的注入器来获取它的 HighlightDirective
实例以及它的 defaultColor
。
DebugElement.properties
affords access to the artificial custom property that is set by the directive.
DebugElement.properties
让你可以访问由指令设置的自定义属性。
Pipes are easy to test without the Angular testing utilities.
管道很容易测试,无需 Angular 测试工具。
A pipe class has one method, transform
, that manipulates the input value into a transformed output value. The transform
implementation rarely interacts with the DOM. Most pipes have no dependence on Angular other than the @Pipe
metadata and an interface.
管道类有一个方法,transform
,用来转换输入值到输出值。 transform
的实现很少与 DOM 交互。 除了 @Pipe
元数据和一个接口外,大部分管道不依赖 Angular。
Consider a TitleCasePipe
that capitalizes the first letter of each word. Here's a naive implementation with a regular expression.
假设 TitleCasePipe
将每个单词的第一个字母变成大写。 下面是使用正则表达式实现的简单代码:
Anything that uses a regular expression is worth testing thoroughly. Use simple Jasmine to explore the expected cases and the edge cases.
任何使用正则表达式的类都值得彻底的进行测试。 使用 Jasmine 来探索预期的用例和极端的用例。
These are tests of the pipe in isolation. They can't tell if the TitleCasePipe
is working properly as applied in the application components.
有些管道的测试程序是孤立的。 它们不能验证 TitleCasePipe
是否在应用到组件上时是否工作正常。
Consider adding component tests such as this one:
考虑像这样添加组件测试程序:
Debug specs in the browser in the same way that you debug an application.
在浏览器中,像调试应用一样调试测试程序 spec。
Reveal the karma browser window (hidden earlier).
显示 Karma
的浏览器窗口(之前被隐藏了)。
Click the DEBUG button; it opens a new browser tab and re-runs the tests.
点击“DEBUG”按钮;它打开一页新浏览器标签并重新开始运行测试程序
Open the browser's “Developer Tools” (Ctrl-Shift-I
on windows; Command-Option-I
in OSX).
打开浏览器的“Developer Tools”(Windows 上的 Ctrl-Shift-I 或者 OSX 上的 `Command-Option-I)。
Pick the "sources" section.
选择“sources”页
Open the 1st.spec.ts
test file (Control/Command-P, then start typing the name of the file).
打开 1st.spec.ts
测试文件(Control/Command-P, 然后输入文件名字)。
Set a breakpoint in the test.
在测试程序中设置断点。
Refresh the browser, and it stops at the breakpoint.
刷新浏览器...然后它就会停在断点上。
This section takes inventory of the most useful Angular testing features and summarizes what they do.
本节将最有用的 Angular 测试功能提取出来,并总结了它们的作用。
The Angular testing utilities include the TestBed
, the ComponentFixture
, and a handful of functions that control the test environment. The TestBed and ComponentFixture classes are covered separately.
Angular 的测试工具集包括 TestBed
、ComponentFixture
和一些用来控制测试环境的便捷函数。 TestBed
和 ComponentFixture
部分单独讲过它们。
Here's a summary of the stand-alone functions, in order of likely utility:
下面是一些独立函数的总结,以使用频率排序:
Function 函数 | Description 说明 |
---|---|
Runs the body of a test ( 在一个特殊的 async 测试区域中运行测试( | |
Runs the body of a test ( 在一个特殊的 fakeAsync 测试区域中运行测试( | |
Simulates the passage of time and the completion of pending asynchronous activities by flushing both timer and micro-task queues within the fakeAsync test zone. 通过在 fakeAsync 测试区域中刷新定时器和微任务(micro-task)队列来仿真时间的流逝以及异步活动的完成。 The curious, dedicated reader might enjoy this lengthy blog post, "Tasks, microtasks, queues and schedules". 好奇和执着的读者可能会喜欢这篇长博客: "Tasks, microtasks, queues and schedules". Accepts an optional argument that moves the virtual clock forward by the specified number of milliseconds, clearing asynchronous activities scheduled within that timeframe. See discussion above. 接受一个可选参数,它可以把虚拟时钟往前推进特定的微秒数。 清除调度到那个时间帧中的异步活动。 参见前面的讨论。 | |
| Injects one or more services from the current 从当前的 |
When a 当 In general, a test should end with no queued tasks. When pending timer tasks are expected, call 一般来讲,测试程序应该以无排队任务结束。 当待执行计时器任务存在时,调用 | |
When a 当 In general, a test should wait for micro-tasks to finish. When pending microtasks are expected, call 一般来说,测试应该等待微任务结束。 当待执行微任务存在时,调用 | |
A provider token for a service that turns on automatic change detection. 一个服务提供商令牌,用于开启自动变更检测。 | |
Gets the current instance of the 获取当前 |
TestBed
类小结linkThe TestBed
class is one of the principal Angular testing utilities. Its API is quite large and can be overwhelming until you've explored it, a little at a time. Read the early part of this guide first to get the basics before trying to absorb the full API.
TestBed
类是 Angular 测试工具的主要类之一。它的 API 很庞大,可能有点过于复杂,直到你一点一点的探索它们。 阅读本章前面的部分,了解了基本的知识以后,再试着了解完整 API。
The module definition passed to configureTestingModule
is a subset of the @NgModule
metadata properties.
传递给 configureTestingModule
的模块定义是 @NgModule
元数据属性的子集。
Each override method takes a MetadataOverride<T>
where T
is the kind of metadata appropriate to the method, that is, the parameter of an @NgModule
, @Component
, @Directive
, or @Pipe
.
每一个重载方法接受一个 MetadataOverride<T>
,这里 T
是适合这个方法的元数据类型,也就是 @NgModule
、@Component
、@Directive
或者 @Pipe
的参数。
The TestBed
API consists of static class methods that either update or reference a global instance of theTestBed
.
TestBed
的 API 包含了一系列静态类方法,它们更新或者引用全局的 TestBed
实例。
Internally, all static methods cover methods of the current runtime TestBed
instance, which is also returned by the getTestBed()
function.
在内部,所有静态方法在 getTestBed()
函数返回的当前运行时间的 TestBed
实例上都有对应的方法。
Call TestBed
methods within a beforeEach()
to ensure a fresh start before each individual test.
在 BeforeEach()
内调用 TestBed
方法,这样确保在运行每个单独测试时,都有崭新的开始。
Here are the most important static methods, in order of likely utility.
这里列出了最重要的静态方法,以使用频率排序:
Methods 方法 | Description 说明 |
---|---|
| The testing shims ( 测试垫片( Call 调用 |
| Compile the testing module asynchronously after you've finished configuring it. You must call this method if any of the testing module components have a 在配置好测试模块之后,异步编译它。 如果测试模块中的任何一个组件具有 After calling 调用完 |
| Create an instance of a component of type 基于当前 |
| Replace metadata for the given 替换指定的 |
| Replace metadata for the given component class, which could be nested deeply within an inner module. 替换指定组件类的元数据,该组件类可能嵌套在一个很深的内部模块中。 |
| Replace metadata for the given directive class, which could be nested deeply within an inner module. 替换指定指令类的元数据,该指令可能嵌套在一个很深的内部模块中。 |
| Replace metadata for the given pipe class, which could be nested deeply within an inner module. 替换指定管道类的元数据,该管道可能嵌套在一个很深的内部模块中。 |
| Retrieve a service from the current 从当前 The What if the service is optional? 如果该服务是可选的呢? The After calling 一旦调用, |
| Initialize the testing environment for the entire test run. 为整套测试的运行初始化测试环境。 The testing shims ( 测试垫片( You may call this method exactly once. If you must change this default in the middle of your test run, call 这个方法只能被调用一次。如果确实需要在测试程序运行期间改变这个默认设置,那么先调用 Specify the Angular compiler factory, a 指定 Angular 编译器工厂, |
| Reset the initial test environment, including the default testing module. 重设初始测试环境,包括默认测试模块在内。 |
A few of the TestBed
instance methods are not covered by static TestBed
class methods. These are rarely needed.
少数 TestBed
实例方法没有对应的静态方法。它们很少被使用。
ComponentFixture
类linkThe TestBed.createComponent<T>
creates an instance of the component T
and returns a strongly typed ComponentFixture
for that component.
TestBed.createComponent<T>
会创建一个组件 T
的实例,并为该组件返回一个强类型的 ComponentFixture
。
The ComponentFixture
properties and methods provide access to the component, its DOM representation, and aspects of its Angular environment.
ComponentFixture
的属性和方法提供了对组件、它的 DOM 和它的 Angular 环境方面的访问。
ComponentFixture
的属性linkHere are the most important properties for testers, in order of likely utility.
下面是对测试最重要的属性,以使用频率排序:
Properties 属性 | Description 说明 |
---|---|
| The instance of the component class created by 被 |
The 与组件根元素关联的 The | |
| The native DOM element at the root of the component. 组件的原生根 DOM 元素。 |
| The 组件的 The 在测试一个拥有 |
ComponentFixture
的方法linkThe fixture methods cause Angular to perform certain tasks on the component tree. Call these method to trigger Angular behavior in response to simulated user action.
fixture 方法使 Angular 对组件树执行某些任务。 在触发 Angular 行为来模拟的用户行为时,调用这些方法。
Here are the most useful methods for testers.
下面是对测试最有用的方法。
Methods 方法 | Description 说明 |
---|---|
| Trigger a change detection cycle for the component. 为组件触发一轮变化检查。 Call it to initialize the component (it calls 调用它来初始化组件(它调用 Runs 之后,运行 |
| Set this to 设置 fixture 是否应该自动试图检测变化。 When autodetect is 当自动检测打开时,测试 fixture 监听 zone 事件,并调用 The default is 默认值是 |
| Do a change detection run to make sure there are no pending changes. Throws an exceptions if there are. 运行一次变更检测来确认没有待处理的变化。如果有未处理的变化,它将抛出一个错误。 |
| If the fixture is currently stable, returns 如果 fixture 当前是稳定的,则返回 |
| Returns a promise that resolves when the fixture is stable. 返回一个承诺,在 fixture 稳定时解析。 To resume testing after completion of asynchronous activity or asynchronous change detection, hook that promise. See above. 要想在完成了异步活动或异步变更检测之后再继续测试,可以对那个承诺对象进行挂钩。 参见 前面。 |
| Trigger component destruction. 触发组件的销毁。 |
The DebugElement
provides crucial insights into the component's DOM representation.
DebugElement
提供了对组件的 DOM 的访问。
From the test root component's DebugElement
returned by fixture.debugElement
, you can walk (and query) the fixture's entire element and component subtrees.
fixture.debugElement
返回测试根组件的 DebugElement
,通过它你可以访问(查询)fixture 的整个元素和组件子树。
Here are the most useful DebugElement
members for testers, in approximate order of utility:
下面是 DebugElement
最有用的成员,以使用频率排序。
Member 成员 | Description 说明 |
---|---|
| The corresponding DOM element in the browser (null for WebWorkers). 与浏览器中 DOM 元素对应(WebWorkers 时,值为 null)。 |
Calling 调用 | |
| Calling 调用 |
| The host dependency injector. For example, the root element's component instance injector. 宿主依赖注入器。 比如,根元素的组件实例注入器。 |
| The element's own component instance, if it has one. 元素自己的组件实例(如果有)。 |
| An object that provides parent context for this element. Often an ancestor component instance that governs this element. 为元素提供父级上下文的对象。 通常是控制该元素的祖级组件实例。 When an element is repeated within 当一个元素被 |
| The immediate |
| The |
| The element tag name, if it is an element. 元素的标签名字,如果它是一个元素的话。 |
| Triggers the event by its name if there is a corresponding listener in the element's 如果在该元素的 If the event lacks a listener or there's some other problem, consider calling 如果事件缺乏监听器,或者有其它问题,考虑调用 |
The callbacks attached to the component's 元素的 | |
This component's injector lookup tokens. Includes the component itself plus the tokens that the component lists in its 组件注入器的查询令牌。 包括组件自己的令牌和组件的 | |
| Where to find this element in the source component template. source 是在源组件模板中查询这个元素的处所。 |
Dictionary of objects associated with template local variables (e.g. 与模板本地变量(比如 |
The DebugElement.query(predicate)
and DebugElement.queryAll(predicate)
methods take a predicate that filters the source element's subtree for matching DebugElement
.
DebugElement.query(predicate)
和 DebugElement.queryAll(predicate)
方法接受一个条件方法, 它过滤源元素的子树,返回匹配的 DebugElement
。
The predicate is any method that takes a DebugElement
and returns a truthy value. The following example finds all DebugElements
with a reference to a template local variable named "content":
这个条件方法是任何接受一个 DebugElement
并返回真值的方法。 下面的例子查询所有拥有名为 content
的模块本地变量的所有 DebugElement
:
The Angular By
class has three static methods for common predicates:
Angular 的 By
类为常用条件方法提供了三个静态方法:
By.all
- return all elements.
By.all
- 返回所有元素
By.css(selector)
- return elements with matching CSS selectors.
By.css(selector)
- 返回符合 CSS 选择器的元素。
By.directive(directive)
- return elements that Angular matched to an instance of the directive class.
By.directive(directive)
- 返回 Angular 能匹配一个指令类实例的所有元素。
It's a good idea to put unit test spec files in the same folder as the application source code files that they test:
将单元测试的 spec 配置文件放到与应用程序源代码文件所在的同一个文件夹中是个好主意,因为:
Such tests are easy to find.
这样的测试程序很容易被找到
You see at a glance if a part of your application lacks tests.
你可以一眼看出应用程序的哪些部分缺乏测试程序。
Nearby tests can reveal how a part works in context.
临近的测试程序可以展示代码是如何在上下文中工作的
When you move the source (inevitable), you remember to move the test.
当你移动代码(无可避免)时,你记得一起移动测试程序
When you rename the source file (inevitable), you remember to rename the test file.
当你重命名源代码文件(无可避免),你记得重命名测试程序文件。
test
文件夹中?linkApplication integration specs can test the interactions of multiple parts spread across folders and modules. They don't really belong to any part in particular, so they don't have a natural home next to any one file.
应用程序的整合测试 spec 文件可以测试横跨多个目录和模块的多个部分之间的互动。 它们不属于任何部分,很自然,没有特别的地方存放它们。
It's often better to create an appropriate folder for them in the tests
directory.
通常,在 test
目录中为它们创建一个合适的目录比较好。
Of course specs that test the test helpers belong in the test
folder, next to their corresponding helper files.
当然,测试助手对象的测试 spec 文件也属于 test
目录,与它们对应的助手文件相邻。
The component DOM tests described in this guide often require extensive setup and advanced techniques whereas the unit tests are comparatively simple.
本指南中讲的组件 DOM 测试通常需要大量的准备工作以及高级技巧,不像只针对类的测试那样简单。
E2E tests are great for high-level validation of the entire system. But they can't give you the comprehensive test coverage that you'd expect from unit tests.
E2E 测试对于整个系统的高层验证非常好用。 但是它们没法给你像单元测试这样全面的测试覆盖率。
E2E tests are difficult to write and perform poorly compared to unit tests. They break easily, often due to changes or misbehavior far removed from the site of breakage.
E2E 测试很难写,并且执行性能也赶不上单元测试。 它们很容易被破坏,而且经常是因为某些远离故障点的修改或不当行为而导致的。
E2E tests can't easily reveal how your components behave when things go wrong, such as missing or bad data, lost connectivity, and remote service failures.
当出错时,E2E 测试不能轻松揭露你的组件出了什么问题, 比如丢失或错误的数据、网络失去连接或远端服务器挂了。
E2E tests for apps that update a database, send an invoice, or charge a credit card require special tricks and back-doors to prevent accidental corruption of remote resources. It can even be hard to navigate to the component you want to test.
如果 E2E 的测试对象要更新数据库、发送发票或收取信用卡,就需要一些特殊的技巧和后门来防止远程资源被意外破坏。 它甚至可能都难以导航到你要测试的组件。
Because of these many obstacles, you should test DOM interaction with unit testing techniques as much as possible.
由于存在这么多障碍,你应该尽可能使用单元测试技术来测试 DOM 交互。