测试一个在Go中使用fmt.Scanf()函数的函数。

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

Testing a function which uses fmt.Scanf() in Go

问题

我想为包含对 fmt.Scanf() 的调用的函数编写测试,但是在传递必需参数给函数时遇到了问题。

有没有更好的方法来解决这个问题,或者我需要模拟 fmt.Scanf()

要测试的函数在这里:
https://github.com/apsdehal/Konsoole/blob/master/parser.go#L28

// 通过查找所有可用设备来初始化网络接口
// 将它们显示给用户,最后根据用户选择其中一个
func Init() *pcap.Pcap {
	devices, err := pcap.Findalldevs()
	if err != nil {
		fmt.Fprintf(errWriter, "[-] Error, pcap failed to iniaitilize")
	}

	if len(devices) == 0 {
		fmt.Fprintf(errWriter, "[-] No devices found, quitting!")
		os.Exit(1)
	}

	fmt.Println("Select one of the devices:")
	var i int = 1
	for _, x := range devices {
		fmt.Println(i, x.Name)
		i++
	}

	var index int

	fmt.Scanf("%d", &index)

	handle, err := pcap.Openlive(devices[index-1].Name, 65535, true, 0)
	if err != nil {
		fmt.Fprintf(errWriter, "Konsoole: %s\n", err)
		errWriter.Flush()
	}
	return handle
}
英文:

I want to write test for function which includes a call to fmt.Scanf(), but I am having problem in passing the required parameter to function.

Is there a better way to do this or I need to mock fmt.Scanf()

Function to be tested is given here:
https://github.com/apsdehal/Konsoole/blob/master/parser.go#L28

// Initializes the network interface by finding all the available devices
// displays them to user and finally selects one of them as per the user
func Init() *pcap.Pcap {
	devices, err := pcap.Findalldevs()
	if err != nil {
		fmt.Fprintf(errWriter, "[-] Error, pcap failed to iniaitilize")
	}

	if len(devices) == 0 {
		fmt.Fprintf(errWriter, "[-] No devices found, quitting!")
		os.Exit(1)
	}

	fmt.Println("Select one of the devices:")
	var i int = 1
	for _, x := range devices {
		fmt.Println(i, x.Name)
		i++
	}

	var index int

	fmt.Scanf("%d", &index)

	handle, err := pcap.Openlive(devices[index-1].Name, 65535, true, 0)
	if err != nil {
		fmt.Fprintf(errWriter, "Konsoole: %s\n", err)
		errWriter.Flush()
	}
	return handle
}

答案1

得分: 3

理论上可以通过将os.Stdin的值与其他os.File进行热交换来改变Scanf的行为。不过,我不会特别推荐仅出于测试目的而这样做。

一个更好的选择是让你的Init函数接受一个io.Reader参数,然后将其传递给Fscanf函数。

然而,总体而言,最好尽可能地将设备初始化代码与输入分离。这可能意味着有一个返回设备列表的函数和一个设备打开函数。你只需要在实时/主要代码中提示进行选择。

英文:

It's theoretically possible to change the behavior of Scanf by hotswapping the value of os.Stdin with some other os.File. I wouldn't particularly recommend it just for testing purposes, though.

A better option would just be to make your Init take in an io.Reader that you pass to Fscanf.

Overall, however, it would likely be better to separate your device initialization code from your input as much as possible. This probably means having a device list returning function and a device opening function. You only need to prompt for selection in live/main code.

huangapple
  • 本文由 发表于 2014年10月5日 18:06:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/26201586.html
匿名

发表评论

匿名网友

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

确定