在golang中从另一个内部调用的模拟函数
Mocking functions called from within another in golang
我正在尝试使用下面的代码存根 os.Stat
和 ioutil.ReadFile(path)
,或者如果您喜欢这里的 go playground [1]
package main
import (
"fmt"
"io/ioutil"
"os"
"strings"
)
func AssignFileValueFrom(path string, val *string) {
var (
tempValue []byte
err error
)
if _, err = os.Stat(path); err == nil {
if err != nil {
fmt.Println("There was a os stat error:", err)
}
tempValue, err = ioutil.ReadFile(path)
if err != nil {
fmt.Println("There was an io read error:", err)
}
*val = strings.TrimSpace(string(tempValue))
}
}
我已经使用 testify 并尝试按照此处的示例进行操作 [2]
package main
import (
"testing"
"github.com/stretchr/testify/mock"
)
type osMock struct {
mock.Mock
}
func (o osMock) Stat(path string) (interface{}, error) {
return nil, nil
}
func TestAssignFileValueFrom(t *testing.T) {
var test string
osm := new(osMock)
osm.On(`Stat`, `./.test`).Return([]byte(`1`), nil)
AssignFileValueFrom(`./.test`, &test)
// assert.Equal(t, `1`, test)
osm.AssertExpectations(t)
}
我做错了什么??
带有 osMock
的代码不会影响 AssignFileValueFrom
函数的执行。直接调用 os.Stat
不会因为你在某处声明了 osMock
而被替换。
要进行实际测试,您应该使用 interface
s 和依赖注入来测试您的代码。
首先, os.Stat
调用必须替换为调用您的结构,该结构实现了定义了相同方法的接口。并且您需要至少创建此接口的 2 个实现:1 - 是要使用的实际工作代码,2 - 模拟要在测试中使用的 osMock
结构。您需要将其注入或传递给 AssignFileValueFrom
,然后使用它来调用 Stat
方法。
谢谢大家的意见我已经重写了我的测试如下..
package main
import (
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
var (
err error
testFile *os.File
test string
)
const (
TestPrefix = `test_file_prefix`
FileContent = `1234`
)
func init() {
testFile, err = ioutil.TempFile(os.TempDir(), TestPrefix)
if err != nil {
panic(err)
}
err = ioutil.WriteFile(testFile.Name(), []byte(FileContent), 0644)
if err != nil {
panic(err)
}
}
func TestAssignFileValueFrom(t *testing.T) {
AssignFileValueFrom(testFile.Name(), &test)
assert.Equal(t, test, FileContent)
}
我正在尝试使用下面的代码存根 os.Stat
和 ioutil.ReadFile(path)
,或者如果您喜欢这里的 go playground [1]
package main
import (
"fmt"
"io/ioutil"
"os"
"strings"
)
func AssignFileValueFrom(path string, val *string) {
var (
tempValue []byte
err error
)
if _, err = os.Stat(path); err == nil {
if err != nil {
fmt.Println("There was a os stat error:", err)
}
tempValue, err = ioutil.ReadFile(path)
if err != nil {
fmt.Println("There was an io read error:", err)
}
*val = strings.TrimSpace(string(tempValue))
}
}
我已经使用 testify 并尝试按照此处的示例进行操作 [2]
package main
import (
"testing"
"github.com/stretchr/testify/mock"
)
type osMock struct {
mock.Mock
}
func (o osMock) Stat(path string) (interface{}, error) {
return nil, nil
}
func TestAssignFileValueFrom(t *testing.T) {
var test string
osm := new(osMock)
osm.On(`Stat`, `./.test`).Return([]byte(`1`), nil)
AssignFileValueFrom(`./.test`, &test)
// assert.Equal(t, `1`, test)
osm.AssertExpectations(t)
}
我做错了什么??
带有 osMock
的代码不会影响 AssignFileValueFrom
函数的执行。直接调用 os.Stat
不会因为你在某处声明了 osMock
而被替换。
要进行实际测试,您应该使用 interface
s 和依赖注入来测试您的代码。
首先, os.Stat
调用必须替换为调用您的结构,该结构实现了定义了相同方法的接口。并且您需要至少创建此接口的 2 个实现:1 - 是要使用的实际工作代码,2 - 模拟要在测试中使用的 osMock
结构。您需要将其注入或传递给 AssignFileValueFrom
,然后使用它来调用 Stat
方法。
谢谢大家的意见我已经重写了我的测试如下..
package main
import (
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
var (
err error
testFile *os.File
test string
)
const (
TestPrefix = `test_file_prefix`
FileContent = `1234`
)
func init() {
testFile, err = ioutil.TempFile(os.TempDir(), TestPrefix)
if err != nil {
panic(err)
}
err = ioutil.WriteFile(testFile.Name(), []byte(FileContent), 0644)
if err != nil {
panic(err)
}
}
func TestAssignFileValueFrom(t *testing.T) {
AssignFileValueFrom(testFile.Name(), &test)
assert.Equal(t, test, FileContent)
}