简体   繁体   English

使用 Jest 模拟 Hyperledger Fabric 链码

[英]Hyperledger Fabric chaincode mocking using Jest

I am trying to add unit tests to my chaincode using Jest.我正在尝试使用 Jest 将单元测试添加到我的链代码中。 From the sample repo here , it is using Sinon to handle the mocking of ChaincodeStub using createStubInstance .这里的示例 repo 中,它使用Sinon使用createStubInstance处理ChaincodeStub的模拟。 I am looking to remove Sinon dependency and handle the mocking part using Jest.我希望删除Sinon依赖并使用 Jest 处理模拟部分。

So far I have been trying:到目前为止,我一直在尝试:

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' });
        });
    });
});

but so far what I am getting is the following error: TypeError: ctx.stub.putState is not a function .但到目前为止,我得到的是以下错误: TypeError: ctx.stub.putState is not a function

Might be missing something there.那里可能缺少一些东西。

Is there also something simpler like the createStubInstance provided by Sinon in Jest ?还有更简单的东西,比如在Jest中由Sinon提供的createStubInstance吗?

After looking into the link sent by @TSN in the comment, I solved it using the following approach:在查看@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' });
        });
    });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM