需要对Golang错误fs.PathError进行单元测试。

huangapple go评论87阅读模式
英文:

Need to unittest golang error fs.PathError

问题

我正在尝试捕获错误并对特定错误对象进行单元测试检查,这是我正在测试的prod函数:

const command = "/tmp/cmd"

type RedisAdapter struct {
	modeStatus bool
}

func (r RedisAdapter) Enable(client domain.client) error {
	cmdArgs := []string{
		"redis-job-shard-pause",
		strconv.Itoa(client.Shard()),
		strconv.Itoa(client.Duration()),
	}
	cmd := fmt.Sprintf("%v", command)
	out, err := exec.Command(cmd, cmdArgs...).Output()
	fmt.Printf("%v", string(out))
	return err
}

以下是运行测试的单元测试代码,当error=nil和error=fs.PathError时进行测试:

func TestEnableService_SetEnable(t *testing.T) {
	type fields struct {
		LoadEnablePort out.EnablePort
	}
	type args struct {
		client domain.Client
	}
	fileNotFound := fs.PathError{
		Op:   "fork/exec",
		Path: "/tmp/cmd",
		Err:  syscall.ENOENT,
	}
	tests := []struct {
		name   string
		fields fields
		args   args
		want   error
	}{
		{
			"Enable Redis",
			fields{
				LoadEnablePort: redis.RedisAdapter{},
			},
			args{
				client: domain.Client{},
			},
			nil,
		},
		{
			"enable_redis_cmd_not_found",
			fields{
				LoadEnablePort: redis.RedisAdapter{},
			},
			args{
				client: domain.Client{},
			},
			&fileNotFound,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			s := EnableService{
				LoadEnablePort: tt.fields.LoadEnablePort,
			}
			if got := s.LoadEnablePort.Enable(tt.args.client); got != tt.want {
				t.Errorf("LoadEnablePort.RedisAdapter.Enable = %v, want %v", got, tt.want)
			}
		})
	}
}

nil测试正常工作,但是当我捕获第二个测试时,即使在调试器中对象完全相同,也无法确定为什么测试失败:

https://i.stack.imgur.com/CTtfk.png

请注意,"got"变量与"tt.want"变量的对象完全相同,最后我得到了以下失败的测试:

=== RUN   TestEnableService_SetEnable/enable_redis_cmd_not_found
    setModeService_test.go:116: LoadEnablePort.RedisAdapter.Enable = fork/exec /tmp/cmd: no such file or directory, want fork/exec /tmp/cmd: no such file or directory
    --- FAIL: TestEnableService_SetEnable/enable_redis_cmd_not_found (549.32s)

非常感谢您的帮助。

英文:

Im trying to catch an error and do a unittest check for the specific error object here is the prod function Im testing:

const command = "/tmp/cmd"

type RedisAdapter struct {
	modeStatus bool
}

func (r RedisAdapter) Enable(client domain.client) error {
	cmdArgs := []string{
		"redis-job-shard-pause",
		strconv.Itoa(client.Shard()),
		strconv.Itoa(client.Duration()),
	}
	cmd := fmt.Sprintf("%v", command)
	out, err := exec.Command(cmd, cmdArgs...).Output()
	fmt.Printf("%v", string(out))
	return err
}

Unittest code that run a test when error=nil and when error=fs.PathError:

func TestEnableService_SetEnable(t *testing.T) {
	type fields struct {
		LoadEnablePort out.EnablePort
	}
	type args struct {
		client domain.Client
	}
	fileNotFound := fs.PathError{
		Op:   "fork/exec",
		Path: "/tmp/cmd",
		Err:  syscall.ENOENT,
	}
	tests := []struct {
		name   string
		fields fields
		args   args
		want   error
	}{
		{
			"Enable Redis",
			fields{
				LoadEnablePort: redis.RedisAdapter{},
			},
			args{
				client: domain.Client{},
			},
			nil,
		},
		{
			"enable_redis_cmd_not_found",
			fields{
				LoadEnablePort: redis.RedisAdapter{},
			},
			args{
				client: domain.Client{},
			},
			&fileNotFound,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			s := EnableService{
				LoadEnablePort: tt.fields.LoadEnablePort,
			}
			if got := s.LoadEnablePort.Enable(tt.args.client); got != tt.want {
				t.Errorf("LoadEnablePort.RedisAdapter.Enable = %v, want %v", got, tt.want)
			}
		})
	}
}

The nil test works fine but when I catch the second test even if the object shows exactly the same in the debugger cannot tell why the test fails:

https://i.stack.imgur.com/CTtfk.png

Notice how the "got" variable is exactly the same as the "tt.want" variable objects and in the end I have the following failed test:

=== RUN   TestEnableService_SetEnable/enable_redis_cmd_not_found
    setModeService_test.go:116: LoadEnablePort.RedisAdapter.Enable = fork/exec /tmp/cmd: no such file or directory, want fork/exec /tmp/cmd: no such file or directory
    --- FAIL: TestEnableService_SetEnable/enable_redis_cmd_not_found (549.32s)

Thanks a lot for your help.

答案1

得分: 2

两个错误值是可比较的,它们持有对fs.PathError结构体的指针。

它们的地址不同,因此它们不相同。

如果你对它们进行解引用,它们是相等的。

https://play.golang.org/p/ZMoEahbyIX_E

你应该使用errors.Iserrors.As

相等运算符在这里有说明https://golang.org/ref/spec#Comparison_operators

它说

...
接口值是可比较的。
如果两个接口值具有相同的动态类型和相等的动态值,或者两者都具有值nil,则它们是相等的。
...
英文:

both error values are comparable, they hold pointers to fs.PathError structs.

Their addresses differs, thus, they are not the same.

If you were dereferencing them, they equal.

https://play.golang.org/p/ZMoEahbyIX_E

You should use errors.Is or errors.As.

Equality operator is specified here https://golang.org/ref/spec#Comparison_operators

It says

...
Interface values are comparable. 
Two interface values are equal if they have 
identical dynamic types and equal dynamic values 
or if both have value nil.
...

huangapple
  • 本文由 发表于 2021年9月10日 06:01:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/69125140.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定