在 golang 函数中测试无法访问的执行路径
test unreachable execution path within golang function
我正在编写单元测试以覆盖下面结构链代码中的所有执行路径。但我看不到到达 JSON.Marshall 失败路径的方法。
如何传递传递给 json.Unmarshal
但无法传递给 json.Marshal
的值?
func (c *MyContract) CreateAsset(ctx contractapi.TransactionContextInterface, values string) (bool, error) {
doctype := "myAsset"
txData := []byte(values)
docData := new(DocData)
docData.DataType = doctype
// validate json input & map to struct
err := json.Unmarshal(txData, &docData)
if err != nil {
return false, fmt.Errorf("failed docData unmarshalling: %s", err.Error())
}
docKey, _ := createKey(ctx, doctype, []string{docData.Key1, docData.Key2})
exists, err := c.DocExists(ctx, docKey)
if err != nil {
return false, fmt.Errorf("could not read from world state %s", err)
} else if exists {
return false, fmt.Errorf("asset already exists")
}
txBytes, err := json.Marshal(docData)
if err != nil {
return false, fmt.Errorf("failed docData bytes marshalling: %s", err.Error())
}
return true, ctx.GetStub().PutState(docKey, txBytes)
}
这是我当前的测试:
func TestCreateAsset(t *testing.T) {
var err error
ctx, _ := setupStub()
c := new(MyContract)
_, err = c.CreateAsset(ctx, "{")
assert.EqualError(t, err, "failed unmarshalling: unexpected end of JSON input", "testing malformed json")
_, err = c.CreateAsset(ctx, "{\"key1\":\"mis\",\"key2\":\"sing\"}")
assert.EqualError(t, err, "could not read from world state some failure")
_, err = c.CreateAsset(ctx, "{\"key1\":\"001\",\"key2\":\"002\"}")
assert.EqualError(t, err, "asset already exists")
}
当无法封送数据中的值时,json.Marshal
函数失败。引发失败的唯一方法是引入一个用于测试的字段,并在测试期间输入错误的值:
type DocData struct {
…
Test interface{} `json:"test,omitempty"`
}
…
var induceFailure interface{}
…
docData.Test = induceFailure
txBytes, err := json.Marshal(docData)
if err != nil {
return false, fmt.Errorf("failed docData bytes marshalling: %s", err.Error())
}
…
func TestMarshlFail(t *testing.T) {
induceFailure = make(chan struct{})
defer func() {
induceFailure= nil
}()
…
获得该行代码的测试覆盖率可能不值得。
与手头的问题无关,这里是对您的代码的一些改进。
包装错误而不是将错误转换为字符串:
return nil, fmt.Errorf("failed docData unmarshalling: %w", err)
因为docData
是一个指针,所以解组时不需要取值的地址。
err := json.Unmarshal(txData, docData)
我正在编写单元测试以覆盖下面结构链代码中的所有执行路径。但我看不到到达 JSON.Marshall 失败路径的方法。
如何传递传递给 json.Unmarshal
但无法传递给 json.Marshal
的值?
func (c *MyContract) CreateAsset(ctx contractapi.TransactionContextInterface, values string) (bool, error) {
doctype := "myAsset"
txData := []byte(values)
docData := new(DocData)
docData.DataType = doctype
// validate json input & map to struct
err := json.Unmarshal(txData, &docData)
if err != nil {
return false, fmt.Errorf("failed docData unmarshalling: %s", err.Error())
}
docKey, _ := createKey(ctx, doctype, []string{docData.Key1, docData.Key2})
exists, err := c.DocExists(ctx, docKey)
if err != nil {
return false, fmt.Errorf("could not read from world state %s", err)
} else if exists {
return false, fmt.Errorf("asset already exists")
}
txBytes, err := json.Marshal(docData)
if err != nil {
return false, fmt.Errorf("failed docData bytes marshalling: %s", err.Error())
}
return true, ctx.GetStub().PutState(docKey, txBytes)
}
这是我当前的测试:
func TestCreateAsset(t *testing.T) {
var err error
ctx, _ := setupStub()
c := new(MyContract)
_, err = c.CreateAsset(ctx, "{")
assert.EqualError(t, err, "failed unmarshalling: unexpected end of JSON input", "testing malformed json")
_, err = c.CreateAsset(ctx, "{\"key1\":\"mis\",\"key2\":\"sing\"}")
assert.EqualError(t, err, "could not read from world state some failure")
_, err = c.CreateAsset(ctx, "{\"key1\":\"001\",\"key2\":\"002\"}")
assert.EqualError(t, err, "asset already exists")
}
当无法封送数据中的值时,json.Marshal
函数失败。引发失败的唯一方法是引入一个用于测试的字段,并在测试期间输入错误的值:
type DocData struct {
…
Test interface{} `json:"test,omitempty"`
}
…
var induceFailure interface{}
…
docData.Test = induceFailure
txBytes, err := json.Marshal(docData)
if err != nil {
return false, fmt.Errorf("failed docData bytes marshalling: %s", err.Error())
}
…
func TestMarshlFail(t *testing.T) {
induceFailure = make(chan struct{})
defer func() {
induceFailure= nil
}()
…
获得该行代码的测试覆盖率可能不值得。
与手头的问题无关,这里是对您的代码的一些改进。
包装错误而不是将错误转换为字符串:
return nil, fmt.Errorf("failed docData unmarshalling: %w", err)
因为
docData
是一个指针,所以解组时不需要取值的地址。err := json.Unmarshal(txData, docData)