我正在尝试构建存根对象,以测试用typescript编写的hyperledger结构链代码。
我感兴趣的存根方法是返回类型为Promise<Iterators.HistoryQueryIterator> & AsyncIterable<Iterators.KeyModification>
的getHistoryForKey
方法。
有人能告诉我如何为此生成存根对象吗
我的代码:
chai.should();
chai.use(chaiAsPromised);
chai.use(sinonChai);
class TestContext implements Context {
public stub: sinon.SinonStubbedInstance<ChaincodeStub> = sinon.createStubInstance(ChaincodeStub);
public clientIdentity: sinon.SinonStubbedInstance<ClientIdentity> = sinon.createStubInstance(ClientIdentity);
public logger = {
getLogger: sinon.stub().returns(sinon.createStubInstance(winston.createLogger().constructor)),
setLevel: sinon.stub(),
};
}
describe('MyContract', () => {
let ctx: TestContext;
let stubAsyncIterator: AsyncIterable<Iterators.KeyModification> & Iterators.HistoryQueryIterator;
beforeEach(() => {
ctx = new TestContext();
stubAsyncIterator = {
async *[Symbol.asyncIterator]() {
yield { isDelete: false, value: Buffer.from('{"entityID":"1000","data":{}}'), timestamp: { seconds: 123, nanos: 111 } as Timestamp, txId: 'txid' } as Iterators.KeyModification;
},
};
ctx.stub.getHistoryForKey.withArgs('1000').resolves(stubAsyncIterator);
});
...
});
此错误与:
error TS2322: Type '{ [Symbol.asyncIterator](): AsyncGenerator<KeyModification, void, undefined>; }' is not assignable to type 'AsyncIterable<KeyModification> & HistoryQueryIterator'.
Type '{ [Symbol.asyncIterator](): AsyncGenerator<KeyModification, void, undefined>; }' is missing the following properties from type 'CommonIterator<KeyModification>': close, next
这是一场相当艰难的比赛。发现只调用原始代码并模拟某些函数比手动重新创建getHistoryForKey
对象更容易。所有这些代码的灵感都来自于单元测试。
这是代码:
import { Context } from 'fabric-contract-api';
import { ChaincodeStub, ClientIdentity, Iterators } from 'fabric-shim';
import { HistoryQueryIterator } from 'fabric-shim/lib/iterators';
import { ChaincodeMessageHandler } from 'fabric-shim/lib/handler';
chai.should();
chai.use(chaiAsPromised);
chai.use(sinonChai);
// test context updated to match fabric-contract-api version 2.4.1
class TestContext implements Context {
public stub: sinon.SinonStubbedInstance<ChaincodeStub> = sinon.createStubInstance(ChaincodeStub);
public clientIdentity: sinon.SinonStubbedInstance<ClientIdentity> = sinon.createStubInstance(ClientIdentity);
public logging = {
getLogger: sinon.stub().returns(sinon.createStubInstance(winston.createLogger().constructor)),
setLevel: sinon.stub(),
};
}
describe('MyContract', () => {
let ctx: TestContext;
let mockHandler: ChaincodeMessageHandler;
let mockResponse: { results: any, hasMore: boolean };
let sandbox;
beforeEach(() => {
...
sandbox = sinon.createSandbox();
mockHandler = sandbox.createStubInstance(ChaincodeMessageHandler);
// we're not actually processing the results, so just fill the results array with the number of items you want to simulate returning in history
mockResponse = {results: [1,2,3,4,5], hasMore: false};
const iterator = new HistoryQueryIterator(mockHandler, 'TestChannelID','txId',mockResponse);
const getResultsFromBytesStub = sinon.stub(iterator, '_getResultFromBytes');
// mocking out the actual responses returned with each iteration
getResultsFromBytesStub.onCall(0).returns({ value: Buffer.from('{"id":"1000","data":{"value": 1}}')});
getResultsFromBytesStub.onCall(1).returns({ value: Buffer.from('{"id":"1000","data":{"value": 2}}')});
getResultsFromBytesStub.onCall(2).returns({ value: Buffer.from('{"id":"1000","data":{"value": 3}}')});
getResultsFromBytesStub.onCall(3).returns({ value: Buffer.from('{"id":"1000","data":{"value": 4}}')});
getResultsFromBytesStub.onCall(4).returns({ value: Buffer.from('{"id":"1000","data":{"value": 5}}')});
ctx.stub.getHistoryForKey.withArgs('1000').resolves(iterator);
});
...