fabric调试chaincode的方法

当写好chaincode之后, 要怎么测试自己的代码正确呢?有两种方法,一种是直接上peer执行,一种是单元测试

Dev模式测试chaincode

直接上peer执行的话,fabric提供了peer的dev运行模式。好处是节省了chaincode的部署步骤,在dev模式下,可以随时修改chaincode,不用走繁琐的chaincode生命周期流程,比如批准,安装,提交等。

其实还是要走这些流程,但走一次即可,便利之处仅在于可随时修改代码

Dev模式要关闭TLS。因此我们不能采用raft模式部署集群,raft模式必须要求开启TLS。因此我们采用Solo模式部署orderer。~~~闪闪发光的传送门。

启动orderer网络后,来看看dev模式下怎么发布chaincode吧

1. 首先把peer启动为dev模式

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
peer node start --peer-chaincodedev=true
peer node start --peer-chaincodedev=true
peer node start --peer-chaincodedev=true

2. 编译chaincode。这个在本地编译即可,不用进入docker

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
go mod vendor
go build -v -o cc.dev chaincode.go
go mod vendor go build -v -o cc.dev chaincode.go
go mod vendor

go build -v -o cc.dev chaincode.go

3. 启动chaincode。这个在本地执行即可,不用进入docker

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
CORE_CHAINCODE_LOGLEVEL=debug CORE_PEER_TLS_ENABLED=false CORE_CHAINCODE_ID_NAME=mycc:1.0 ./cc.dev -peer.address 127.0.0.1:8150
CORE_CHAINCODE_LOGLEVEL=debug CORE_PEER_TLS_ENABLED=false CORE_CHAINCODE_ID_NAME=mycc:1.0 ./cc.dev -peer.address 127.0.0.1:8150
CORE_CHAINCODE_LOGLEVEL=debug CORE_PEER_TLS_ENABLED=false CORE_CHAINCODE_ID_NAME=mycc:1.0 ./cc.dev -peer.address 127.0.0.1:8150

4. 注册批准chaincode。这些操作如果使用了cli容器,就得在cli中操作

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 批准chaincode定义
peer lifecycle chaincode approveformyorg -o orderer.dev:7050 --channelID channel1 --name mycc --version 1.0 --sequence 1 --package-id mycc:1.0
# 提交chaincode定义
peer lifecycle chaincode commit -o orderer.dev:7050 --channelID channel1 --name mycc --version 1.0 --sequence 1 --peerAddresses peer1.dev:8050
# 批准chaincode定义 peer lifecycle chaincode approveformyorg -o orderer.dev:7050 --channelID channel1 --name mycc --version 1.0 --sequence 1 --package-id mycc:1.0 # 提交chaincode定义 peer lifecycle chaincode commit -o orderer.dev:7050 --channelID channel1 --name mycc --version 1.0 --sequence 1 --peerAddresses peer1.dev:8050
# 批准chaincode定义
peer lifecycle chaincode approveformyorg  -o orderer.dev:7050 --channelID channel1 --name mycc --version 1.0 --sequence 1  --package-id mycc:1.0
# 提交chaincode定义
peer lifecycle chaincode commit -o orderer.dev:7050 --channelID channel1 --name mycc --version 1.0 --sequence 1  --peerAddresses peer1.dev:8050

至此,chaincode已经在dev模式下启动了,我们来调用一个试试:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# 调用函数
peer chaincode invoke -o orderer.dev:7050 -C channel1 -n mycc -c '{"function":"InitLedger","Args":[]}'
# 查看数据
peer chaincode query -C channel1 -n mycc -c '{"Args":["GetAllAssets"]}'
# 调用函数 peer chaincode invoke -o orderer.dev:7050 -C channel1 -n mycc -c '{"function":"InitLedger","Args":[]}' # 查看数据 peer chaincode query -C channel1 -n mycc -c '{"Args":["GetAllAssets"]}'
# 调用函数
peer chaincode invoke -o orderer.dev:7050 -C channel1 -n mycc -c '{"function":"InitLedger","Args":[]}'
# 查看数据
peer chaincode query -C channel1 -n mycc -c '{"Args":["GetAllAssets"]}'

但要注意的是,在dev模式下的chaincode, Application是无法调用的,会报chaincode没有安装的错误,仔细想想,我们确实也没有执行install动作。因此,和Application联调的时候,老老实实的走正规流程发布chaincode吧

chaincode的单元测试

单元测试也是测试代码非常重要的步骤。chaincode的单元测试采用的是mock手段,即模拟的逻辑来替代执行合约的PutState,GetState等读写行为。因此,单元测试并不能检验chaincode的链上读写功能。单元测试的主要目的,是测试chaincode的业务逻辑是否完整。

chaincode单元测试的例子:~~~闪闪发光的传送门

mock的引入和使用:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import (
...
"github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go/chaincode/mocks"
)
func TestCreateAsset(t *testing.T) {
//设置mock
chaincodeStub := &mocks.ChaincodeStub{}
transactionContext := &mocks.TransactionContext{}
transactionContext.GetStubReturns(chaincodeStub)
assetTransfer := chaincode.SmartContract{}
err := assetTransfer.CreateAsset(transactionContext, "", "", 0, "", 0)
require.NoError(t, err)
//预先设置GetState的值和返回错误,下一条指令assetTransfer.CreateAsset调用的时候,就会返回
//本处设置的值,模拟链上的数据读写,这是mock目的所在
chaincodeStub.GetStateReturns([]byte{}, nil)
err = assetTransfer.CreateAsset(transactionContext, "asset1", "", 0, "", 0)
require.EqualError(t, err, "the asset asset1 already exists")
chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset"))
err = assetTransfer.CreateAsset(transactionContext, "asset1", "", 0, "", 0)
require.EqualError(t, err, "failed to read from world state: unable to retrieve asset")
}
import ( ... "github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go/chaincode/mocks" ) func TestCreateAsset(t *testing.T) { //设置mock chaincodeStub := &mocks.ChaincodeStub{} transactionContext := &mocks.TransactionContext{} transactionContext.GetStubReturns(chaincodeStub) assetTransfer := chaincode.SmartContract{} err := assetTransfer.CreateAsset(transactionContext, "", "", 0, "", 0) require.NoError(t, err) //预先设置GetState的值和返回错误,下一条指令assetTransfer.CreateAsset调用的时候,就会返回 //本处设置的值,模拟链上的数据读写,这是mock目的所在 chaincodeStub.GetStateReturns([]byte{}, nil) err = assetTransfer.CreateAsset(transactionContext, "asset1", "", 0, "", 0) require.EqualError(t, err, "the asset asset1 already exists") chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) err = assetTransfer.CreateAsset(transactionContext, "asset1", "", 0, "", 0) require.EqualError(t, err, "failed to read from world state: unable to retrieve asset") }
import (
	...
	"github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go/chaincode/mocks"
)

func TestCreateAsset(t *testing.T) {
//设置mock
	chaincodeStub := &mocks.ChaincodeStub{}
	transactionContext := &mocks.TransactionContext{}
	transactionContext.GetStubReturns(chaincodeStub)

	assetTransfer := chaincode.SmartContract{}
	err := assetTransfer.CreateAsset(transactionContext, "", "", 0, "", 0)
	require.NoError(t, err)
        
//预先设置GetState的值和返回错误,下一条指令assetTransfer.CreateAsset调用的时候,就会返回
//本处设置的值,模拟链上的数据读写,这是mock目的所在
	chaincodeStub.GetStateReturns([]byte{}, nil)
	err = assetTransfer.CreateAsset(transactionContext, "asset1", "", 0, "", 0)
	require.EqualError(t, err, "the asset asset1 already exists")

	chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset"))
	err = assetTransfer.CreateAsset(transactionContext, "asset1", "", 0, "", 0)
	require.EqualError(t, err, "failed to read from world state: unable to retrieve asset")
}

Ref



《 “fabric调试chaincode的方法” 》 有 4 条评论

  1. how can i get cytotec tablets 5 leads to reporter expression in the cells surrounding the neural tube in the rostral region red arrows in C and C

  2. Recently, he has launched his latest training program and workout guide, BIG, which is getting huge attention from around the fitness industry priligy farmacias del ahorro

  3. Plastic Surgery, Department of Biomedicine and Prevention, Tor Vergata University, Rome, Italy priligy medication Such dormant tumors exhibited features of both population level and cellular dormancy

回复 agodelo 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About Me

一位程序员,会弹吉他,喜欢读诗。
有一颗感恩的心,一位美丽的妻子,两个可爱的女儿
mail: geraldlee0825@gmail.com
github: https://github.com/lisuxiaoqi
medium: https://medium.com/@geraldlee0825