首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

对使用 Go 为 Hyperledger Fabric v0.6 编写的区块链链代码进行单元测试(5)

对使用 Go 为 Hyperledger Fabric v0.6 编写的区块链链代码进行单元测试(5)

Invoke 方法实现让我们使用测试驱动开发来实现 shim.Chaincode.Invoke 方法。Invoke 方法由链代码基础架构调用,它传入                ChaincodeStubInterface 的合适实例,以及链代码的调用方(客户应用程序)所传入的函数名和参数。
要求
  • Invoke 方法应检查输入函数名称参数,并将执行任务委托给合适的处理函数。
  • 如果输入函数名称是无效的,Invoke 方法会返回一个错误。
  • Invoke 方法应基于链代码的调用方的交易证书,实现/委托访问控制和权限管理。应该只允许 Bank_Admin                    调用 CreateLoanApplication 方法。
第一个测试将验证上面的 “要求 3” 中列出的功能。
清单 14. TestInvokeValidation                    测试的代码段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func TestInvokeValidation(t *testing.T) {
    fmt.Println("Entering TestInvokeValidation")

    attributes := make(map[string][]byte)
    attributes["username"] = []byte("vojha24")
    attributes["role"] = []byte("client")

    stub := shim.NewCustomMockStub("mockStub", new(SampleChaincode), attributes)
    if stub == nil {
        t.Fatalf("MockStub creation failed")
    }

    _, err := stub.MockInvoke("t123", "CreateLoanApplication", []string{loanApplicationID, loanApplication})
    if err == nil {
        t.Fatalf("Expected unauthorized user error to be returned")
    }

}




第 1 部分                中已经解释过,链代码的调用方的交易证书可能包含用户定义的属性。这些属性为在链代码中执行访问控制和权限发挥着关键作用。
第 5 和第 6 行添加用户名和角色属性,然后这些属性被传递给 CustomMockStub                构造函数。这些属性应有助于模拟可从链代码调用方的交易证书检索的属性。
第 13 行使用 stub.MockInvoke 方法模拟链代码基础架构在运行时应如何直接调用                shim.Chaincode.Invoke 方法。
MockInvoke 方法接受交易 ID(由区块链基础架构在运行时生成)、函数名和输入参数。
再次运行该测试套件。跟预期一样,TestInvokeValidation                    测试将会失败。这是测试的红色阶段。
1 --- FAIL: TestInvokeValidation (0.00s)
2         sample_chaincode_test.go:158 Expected unauthorized user error to be returned
3 FAIL
4 exit status 1




现在,在 sample_chaincode.go 中的 Invoke                    方法中编写通过此测试所需的最少量代码。这是测试的绿色阶段。
清单 15. 为了通过测试而需要在 sample_chaincode.go 中的 Invoke                    方法中包含的最少量代码
1
2
3
4
func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    fmt.Println("Entering Invoke")
    return nil, errors.New("unauthorized user")
}




现在运行该测试套件。TestInvokeValidation 测试将会通过。
1 Entering TestInvokeValidation
2 2017/03/06 23:22:27 MockStub( mockStub &{} )
3 Entering Invoke
4 PASS




下一个测试将传入正确的角色 Bank_Admin 并期望测试通过。
清单 16. TestInvokeValidation2                的代码段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func TestInvokeValidation2(t *testing.T) {
    fmt.Println("Entering TestInvokeValidation")

    attributes := make(map[string][]byte)
    attributes["username"] = []byte("vojha24")
    attributes["role"] = []byte("Bank_Admin")

    stub := shim.NewCustomMockStub("mockStub", new(SampleChaincode), attributes)
    if stub == nil {
        t.Fatalf("MockStub creation failed")
    }

    _, err := stub.MockInvoke("t123", "CreateLoanApplication", []string{loanApplicationID, loanApplication})
    if err != nil {
        t.Fatalf("Expected CreateLoanApplication to be invoked")
    }

}




运行该测试套件。跟预期一样,TestInvokeValidation2 测试将会失败。要通过此测试,我们现在必须重构                sample_chaincode.go 中的 Invoke 的代码。
清单 17. 重构 sample_chaincode.go 中的 Invoke                方法代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    fmt.Println("Entering Invoke")
     
    ubytes, _ := stub.ReadCertAttribute("username")
    rbytes, _ := stub.ReadCertAttribute("role")

    username := string(ubytes)
    role := string(rbytes)

    if role != "Bank_Admin" {
        return nil, errors.New("caller with " + username + " and role " + role + " does not have
         access to invoke CreateLoanApplication")
    }
    return nil, nil
}




现在运行该测试套件。TestInvokeValidation2 测试将会通过。
清单 18. 测试要求 1 和要求 2                中列出的功能的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func TestInvokeFunctionValidation(t *testing.T) {
    fmt.Println("Entering TestInvokeFunctionValidation")

    attributes := make(map[string][]byte)
    attributes["username"] = []byte("vojha24")
    attributes["role"] = []byte("Bank_Admin")

    stub := shim.NewCustomMockStub("mockStub", new(SampleChaincode), attributes)
    if stub == nil {
        t.Fatalf("MockStub creation failed")
    }

    _, err := stub.MockInvoke("t123", "InvalidFunctionName", []string{})
    if err == nil {
        t.Fatalf("Expected invalid function name error")
    }

}




第 14 行验证是否从 Invoke 返回了合适的错误消息。
运行 TestInvokeFunctionValidation 测试。跟预期一样,它将失败并抛出以下输出:
1 --- FAIL: TestInvokeFunctionValidation (0.00s)
2         sample_chaincode_test.go:117 Expected invalid function name error
3 FAIL
4 exit status 1
返回列表