1、概述

​ ​ ​ ​ ​ ​ 链码运行的环境通常是在docker容器中,调用需要与peer进行交互,而peer又依赖于orderer、leveldb/couchdb等服务,因此本地IDE开发的链码,要想测试,通常来说是一件比较麻烦的事情。
​​ ​ ​ ​ ​ ​ 在fabric中,开发链码用到的shim包除了给我们提供Chaincode和ChaincodeStubInterface两个接口用于开发之外,还有一个结构体MockStub,专门供我们做test测试。这个MockStub实现了ChaincodeStubInterface接口的所有方法,实际上我们做测试的时候,真正invoke的只是MockStub中的方法实现。而在MockStub这些方法的实现中,有一些方法是实现不了的:

  • 需要couchdb才能支持的数据查询方法,MockStub的实现方式都是不处理,直接返回nil;
  • 查询不到数据修改的历史记录;
  • 获取交易信息类型,比如说交易ID、ChannelID、交易提交者的身份信息等等,返回的都是空字段;
  • 发送事件是没有作用的;
  • 无法跨链调用其他链码;
2、流程
1)链码初始化
/*
  res := stub.MockInit("1", args)
    - 1为uuid,用于链码开始前和结束后开始事务的标志,无实际意义
    - args为初始化需要的参数
*/
stub.MockInit(uuid string, args [][]byte)
2)链码调用
/*
	 res := stub.MockInvoke("1", args)
	  - 1为uuid,用于链码开始前和结束后开始事务的标志,无实际意义
	  - args为invoke传入的参数
*/
stub.MockInvoke(uuid string, args [][]byte)
3)测试流程
func Test(t *testing.T) {
  // SimpleChaincode为链码逻辑中实现的实际struct
  cc := new(SimpleChaincode)
  // 获取MockStub对象, 传入名称和链码实体
  stub := shim.NewMockStub("SimpleChaincode", cc)
  
  // 构造初始化args,在example02中,初始化参数有四个,分别是给两个对象初始化值
  initArgs := [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte("200")}
  // 初始化链码
  stub.MockInit("1", initArgs)
  fmt.Println(res)
  
  // 调用invoke方法中的query方法,查询a的值,得到a为100,说明初始化成功
  queryArgs := [][]byte{[]byte("query"), []byte("a")}
  res = stub.MockInvoke("1", queryArgs)
  fmt.Println(res)


  // 调用invoke方法中的invoke方法,a给b转账10
  invokeArgs := [][]byte{[]byte("invoke"), []byte("a"), []byte("b"), []byte("10")}
  res = stub.MockInvoke("1", invokeArgs)
  fmt.Println(res)


  // 再一次调用invoke方法中query方法,查询a的值,此时a的值为90,说明转账成功
  queryArgs = [][]byte{[]byte("query"), []byte("a")}
  res = stub.MockInvoke("1", queryArgs)
  fmt.Println(res)
}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐