我参考了以下博文:https://vsavkin.com/three-ways-to-test-angular-2-components-dcea8e90bd8d#.he4b4rw65
在其中一项测试中(见下文),BehaviorSubject
用于充当间谍。
我理解Subject
(Observable
+ Observer
)的要求,但为什么要使用BehaviorSubject
代替普通Subject
?
有人可以解释一下吗?
describe('ComposeCmp', () => {
let actions: BehaviorSubject<any>;
let time: CurrentTime;
beforeEach(() => {
// this subject acts as a "spy"
actions = new BehaviorSubject(null);
// dummy implementation of CurrentTime
time = () => '2016-08-19 9:10AM';
});
it('emits a reply action on submit', () => {
// a fake activated route
const route = {
snapshot: {
root: {
firstChild: { params: { id: 11 } }
}
}
};
const c = new ComposeCmp(<any>route, time, actions);
// performing an action
c.form.setValue({
title: 'Categorical Imperative vs Utilitarianism',
body: 'What is more practical in day-to-day life?'
});
c.onSubmit();
// reading the emitted value from the subject
// to make sure it matches our expectations
expect(actions.value.conversationId).toEqual(11);
expect(actions.value.payload).toEqual({
title: 'Categorical Imperative vs Utilitarianism',
body: 'What is more practical in day-to-day life?',
createdAt: '2016-08-19 9:10AM'
});
});
});
编辑:我有一个进一步的询问:actions
BehaviorSubject
订阅了什么,订阅者是什么?被测组件如下:
@Component({moduleId: module.id, templateUrl: 'compose.html'})
class ComposeCmp {
form = new FormGroup({
title: new FormControl('', Validators.required),
body: new FormControl('')
});
constructor(private route: ActivatedRoute,
private currentTime: CurrentTime,
private actions: Actions) {}
onSubmit() {
const routerStateRoot = this.route.snapshot.root;
const conversationRoute = routerStateRoot.firstChild;
const conversationId = +conversationRoute.params['id'];
const payload = Object.assign({},
this.form.value,
{createdAt: this.currentTime()});
this.actions.next({
type: 'reply',
conversationId: conversationId,
payload: payload
});
}
}
答案 0 :(得分:2)
实际上非常简单:)
在测试间谍时,您可以跟踪。意思是,你可以问一下间谍的事情,比如&#34;你的价值是什么&#34;,&#34;你被称为&#34;或者&#34;你用什么参数调用了#34;。
在你的情况下,间谍充当动作流的模拟(但我猜你已经知道了)。
主题与 BehaviorSubject 之间的差异最好显示在如下的简单示例中:
const s = new Rx.Subject();
s.next(5);
console.log('Subject:', s.value);
const bs = new Rx.BehaviorSubject();
bs.next(5);
console.log('BehaviorSubject:', bs.value);
&#13;
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>
&#13;
tl; dr; BehaviorSubject 存储其最新值,您可以通过.value
获取。 主题不存储任何内容。在测试中,您需要验证是否将正确的数据(.next()
)推送到操作流(actions
)。使用BehaviorSubject
,您可以对此进行测试。
为什么不需要订阅者?
这是因为调用next()
也会设置value
。请参阅BehaviorSubject
的源代码:
next(value: T): void {
super.next(this._value = value);
}