【问题标题】:Hyperledger Fabric chaincode mocking using Jest使用 Jest 模拟 Hyperledger Fabric 链码
【发布时间】:2022-06-20 20:35:13
【问题描述】:

我正在尝试使用 Jest 将单元测试添加到我的链代码中。从示例 repo here 中,它使用Sinon 来处理使用createStubInstanceChaincodeStub 的模拟。我希望删除 Sinon 依赖项并使用 Jest 处理模拟部分。

到目前为止我一直在尝试:

const { ChaincodeStub } = require('fabric-shim');

const MyContract = require('./myContract');

describe('Asset Transfer Basic Tests', () => {
    let transactionContext;
    let mockChaincode;
    let asset;

    beforeEach(() => {
        transactionContext = new Context();

        mockChaincode = ChaincodeStub;

        jest.mock('fabric-shim', () => ({
            ChaincodeStub: jest.fn().mockImplementation(() => ({
                deleteState: jest.fn().mockImplementation(async (key) => {
                    if (mockChaincode.states) {
                        delete mockChaincode.states[key];
                    }
                    return Promise.resolve(key);
                }),
                getState: jest.fn().mockImplementation(async (key) => {
                    let ret;
                    if (mockChaincode.states) {
                        ret = mockChaincode.states[key];
                    }
                    return Promise.resolve(ret);
                }),
                getStateByRange: jest.fn().mockImplementation(async () => {
                    function* internalGetStateByRange() {
                        if (mockChaincode.states) {
                            // Shallow copy
                            const copied = { ...mockChaincode.states };

                            for (const key in copied) {
                                yield { value: copied[key] };
                            }
                        }
                    }

                    return Promise.resolve(internalGetStateByRange());
                }),
                putState: jest.fn().mockImplementation((key, value) => {
                    if (!mockChaincode.states) {
                        mockChaincode.states = {};
                    }
                    mockChaincode.states[key] = value;
                }),
            })),
        }));

        transactionContext.setChaincodeStub(mockChaincode);

        asset = {
            birthDay: '1966-05-31T00:00:00.000Z',
            firstName: 'Federico',
            gender: 'male',
            id: '09c2f565-9923-4b78-bd1c-ff635a70a880',
            lastName: 'Villegas',
        };
    });

    describe('Test InitLedger', (done) => {
        it('should return error on InitLedger', async () => {
            mockChaincode.putState.rejects('failed inserting key');
            const myContract = new MyContract();
            try {
                await myContract.initLedger(transactionContext);
                done.fail('initLedger should have failed');
            } catch (err) {
                expect(err.name).toBe('failed inserting key');
            }
        });

        it('should return success on InitLedger', async () => {
            const myContract = new MyContract();
            await myContract.initLedger(transactionContext);
            const ret = JSON.parse(
                (
                    await mockChaincode.getState(
                        '09c2f565-9923-4b78-bd1c-ff635a70a880',
                    )
                ).toString(),
            );
            expect(ret).toEqual({ ...asset, docType: 'user' });
        });
    });
});

但到目前为止,我得到的是以下错误:TypeError: ctx.stub.putState is not a function

那里可能缺少一些东西。

是否还有像SinonJest 中提供的createStubInstance 这样更简单的东西?

【问题讨论】:

标签: javascript unit-testing jestjs hyperledger-fabric


【解决方案1】:

查看@TSN在评论中发送的链接后,我使用以下方法解决了它:

jest.doMock('fabric-shim');

const { ChaincodeStub } = require('fabric-shim');

const MyContract = require('./myContract');

describe('Asset Transfer Basic Tests', () => {
    let transactionContext;
    let chaincodeStub;
    let asset;

    beforeEach(() => {
        transactionContext = new Context();

        chaincodeStub = new ChaincodeStub();
        transactionContext.setChaincodeStub(chaincodeStub);

        chaincodeStub.putState = jest.fn((key, value) => {
            if (!chaincodeStub.states) {
                chaincodeStub.states = {};
            }
            chaincodeStub.states[key] = value;
        });

        chaincodeStub.getState = jest.fn(async (key) => {
            let ret;
            if (chaincodeStub.states) {
                ret = chaincodeStub.states[key];
            }
            return Promise.resolve(ret);
        });

        chaincodeStub.deleteState = jest.fn(async (key) => {
            if (chaincodeStub.states) {
                delete chaincodeStub.states[key];
            }
            return Promise.resolve(key);
        });

        chaincodeStub.getStateByRange = jest.fn(async () => {
            function* internalGetStateByRange() {
                if (chaincodeStub.states) {
                    // Shallow copy
                    const copied = { ...chaincodeStub.states };

                    for (const key in copied) {
                        yield { value: copied[key] };
                    }
                }
            }

            return Promise.resolve(internalGetStateByRange());
        });

        asset = {
            birthDay: '1966-05-31T00:00:00.000Z',
            firstName: 'Federico',
            gender: 'male',
            id: '09c2f565-9923-4b78-bd1c-ff635a70a880',
            lastName: 'Villegas',
        };
    });

    describe('Test initLedger', (done) => {
        it('should return error on initLedger', async () => {
            chaincodeStub.putState = () =>
                Promise.reject(new Error('failed inserting key'));
            const myContract = new MyContract();
            try {
                await myContract.initLedger(transactionContext);
                done.fail('initLedger should have failed');
            } catch (err) {
                expect(err.message).toBe('failed inserting key');
            }
        });

        it('should return success on initLedger', async () => {
            const myContract = new MyContract();
            await myContract.initLedger(transactionContext);
            const ret = JSON.parse(
                (
                    await chaincodeStub.getState(
                        '09c2f565-9923-4b78-bd1c-ff635a70a880',
                    )
                ).toString(),
            );
            expect(ret).toEqual({ ...asset, docType: 'user' });
        });
    });
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    相关资源
    最近更新 更多