JoG*_*JoG 5 rxjs apollo graphql angular rxjs-marbles
我想在 Angular 中测试 GraphQL 订阅
subscribeToMore
我按照有关客户端测试的 Apollo 文档成功地进行了良好的测试:
const ENTITY_QUERY = gql`
query EntityList {
entityList {
id
content
}
}
`;
const ENTITY_SUBSCRIPTION = gql`
subscription OnNameChanged {
nameChanged {
id
name
}
}
`;
describe('Test Subscription', () => {
let backend: ApolloTestingController;
let apollo: Apollo;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ApolloTestingModule],
providers: [
{
provide: APOLLO_TESTING_CACHE,
useValue: new InMemoryCache({ addTypename: true })
}
]
});
backend = TestBed.get(ApolloTestingController);
apollo = TestBed.get(Apollo);
});
it('should subscribe and return updated entity', done => {
const queryRef: QueryRef<any> = apollo.watchQuery({ query: ENTITY_QUERY });
queryRef.subscribeToMore({
document: ENTITY_SUBSCRIPTION,
updateQuery: (entityList, { subscriptionData }) => ({
entityList: entityList.map(entity => {
// update name of corresponding entity in cache
return entity.id === subscriptionData.data.nameChanged.id
? {
...entity,
name: subscriptionData.data.nameChanged.name
}
: entity;
})
})
});
const queryResult = [{ id: '1', name: 'John' }, { id: '2', name: 'Andrew' }];
const subscriptionResult = { id: '1', name: 'Marc' };
const expectedEntitiesWhenQuery = queryResult;
const expectedEntitiesAfterSubscriptionUpdate = [subscriptionResult, { id: '2', name: 'Andrew' }];
let firstQueryTick = true;
// the subscription should be done before the flush in other case the operation backends would not be available
queryRef.valueChanges.subscribe(result => {
try {
if (firstQueryTick) {
// first test the query result returns the expected
expect(result).toEqual(expectedEntitiesWhenQuery);
firstQueryTick = false;
} else {
// then, when the subscription return a new name, test that the result is modified
expect(result).toEqual(expectedEntitiesAfterSubscriptionUpdate);
done();
}
} catch (error) {
fail(error);
}
});
// retrieves the query operation backend
const backendSubscription = backend.expectOne('OnNameChanged');
// retrieves the subscription operation backend
const backendQuery = backend.expectOne('EntityList');
// Mock by flushing data to query
backendQuery.flush({ data: { entityList: queryResult } });
// Then Mock by flushing data to subscription
backendSubscription.flush({ data: { nameChanged: subscriptionResult } });
});
afterEach(() => {
backend.verify();
});
});
Run Code Online (Sandbox Code Playgroud)
但正如您所看到的,该部分结果的验证subscribe
对于变量来说并不是很干净firstQueryTick
......想象一下,如果我想测试 10 个结果......
所以我尝试使用rxjs 大理石测试来替换这部分:
import { APOLLO_TESTING_CACHE, ApolloTestingController, ApolloTestingModule } from 'apollo-angular/testing';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { TestBed } from '@angular/core/testing';
import { Apollo, QueryRef } from 'apollo-angular';
import gql from 'graphql-tag';
import { TestScheduler } from 'rxjs/testing';
const ENTITY_QUERY = gql`
query EntityList {
entityList {
id
content
}
}
`;
const ENTITY_SUBSCRIPTION = gql`
subscription OnNameChanged {
nameChanged {
id
name
}
}
`;
describe('Test Subscription', () => {
let backend: ApolloTestingController;
let apollo: Apollo;
let scheduler: TestScheduler;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ApolloTestingModule],
providers: [
{
provide: APOLLO_TESTING_CACHE,
useValue: new InMemoryCache({ addTypename: true })
}
]
});
backend = TestBed.get(ApolloTestingController);
apollo = TestBed.get(Apollo);
scheduler = new TestScheduler((actual, expected) => {
expect(actual).toEqual(expected);
});
});
it('should subscribe and return updated entity', done => {
const queryRef: QueryRef<any> = apollo.watchQuery({ query: ENTITY_QUERY });
queryRef.subscribeToMore({
document: ENTITY_SUBSCRIPTION,
updateQuery: (entityList, { subscriptionData }) => ({
entityList: entityList.map(entity => {
// update name of corresponding entity in cache
return entity.id === subscriptionData.data.nameChanged.id
? {
...entity,
name: subscriptionData.data.nameChanged.name
}
: entity;
})
})
});
const queryResult = [{ id: '1', name: 'John' }, { id: '2', name: 'Andrew' }];
const subscriptionResult = { id: '1', name: 'Marc' };
/////////////////////////////NEW PART
scheduler.run(({ expectObservable }) => {
// the source is the query observable
const source$ = queryRef.valueChanges;
const expectedMarble = 'x-y|';
const expectedValues = { x: queryResult, y: [subscriptionResult, { id: '2', name: 'Andrew' }] };
// this is subscribing and validating at the same time so it is not possible to do something between the subscription and the flush of values from rxjs
expectObservable(source$).toBe(expectedMarble, expectedValues);
});
/////////////////////////////
// this will not be called because the test is already failing with expectObservable, if we put this part before, it will fail because the subscription is not already done...
const backendSubscription = backend.expectOne('OnNameChanged');
const backendQuery = backend.expectOne('EntityList');
backendQuery.flush({ data: { entityList: queryResult } });
backendSubscription.flush({ data: { nameChanged: subscriptionResult } });
});
afterEach(() => {
backend.verify();
});
});
Run Code Online (Sandbox Code Playgroud)
经过多次尝试后,我无法使其工作,因为它正在“同时”expectObservable
执行subscribe
+ ,我需要:validation
subscribe
是否可以在和使用 rxjs 测试弹珠之间进行操作validation
?
归档时间: |
|
查看次数: |
590 次 |
最近记录: |