如何注入正在服务的文档?

我有一个角度2的应用程序。为了在测试中模仿 Document对象,我想将它注入到服务中,比如:

import { Document } from '??'


@Injectable()
export class MyService {
constructor(document: Document) {}
}

使用内部 getDOM()方法Title业务。

有什么简单的方法可以将 Document注入到服务中吗?还有,我应该如何在 providers数组中引用它?

93604 次浏览

This has been supported by Angular for a while.

You can use the DOCUMENT constant provided by the @angular/common package.

Description of the DOCUMENT constant (taken from the API documentation):

A DI Token representing the main rendering context. In a browser, this is the DOM Document.

An example is as shown below:

my-service.service.ts:

import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';


@Injectable()
export class MyService {
constructor(@Inject(DOCUMENT) private document: Document) {}
}

my-service.service.spec.ts

import { provide } from '@angular/core';
import { DOCUMENT } from '@angular/common';


import { MyService } from './my-service';


class MockDocument {}


describe('MyService', () => {
beforeEachProviders(() => ([
provide(DOCUMENT, { useClass: MockDocument }),
MyService
]));


...
});

in addition to @Günter Zöchbauer's answer.

Angular define DOCUMENT as an InjectionToken

export const DOCUMENT = new InjectionToken<Document>('DocumentToken');

dom_tokens.ts

And inject it with document in browser.ts

{provide: DOCUMENT, useFactory: _document, deps: []}




export function _document(): any {
return document;
}

Therefore, when we use it, we just need to inject @Inject(DOCUMENT)

or use the token directly in deps:[DOCUMENT]

I'm unable to comment directly on adamdport's question (not yet 50 rep points), but here it is as stated in the angular docs.

Blockquote @GünterZöchbauer it looks like DOCUMENT is deprecated. Any idea how to do this once it's gone? For example, how would I set the favicon dynamically?

Instead of importing from platform browser like so:

import { DOCUMENT } from '@angular/platform-browser';

Import it from angular common:

import {DOCUMENT} from '@angular/common';
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';


@Injectable()
export class MyService {
constructor(@Inject(DOCUMENT) private document) {}
}

It's the ": Document" that's causing the problem.