如何模拟 DNS 请求?(miekg/dns)

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

How to mock a DNS request? (miekg/dns)

问题

我有这段小代码来解释我试图测试的代码库。为了简化问题,我跳过了错误检查。

func lastCNAME(domain string) (lastCNAME string) {
    ns := "8.8.8.8:53"

    c := dns.Client{}
    m := dns.Msg{}
    m.SetQuestion(domain, dns.TypeA)
    r, _, _ := c.Exchange(&m, ns)
    // Last CNAME
    for _, ans := range r.Answer {
        cname, ok := ans.(*dns.CNAME)
        if ok {
            lastCNAME = cname.Target
        }
    }
    return lastCNAME
}

如何最好地模拟对名字服务器 8.8.8.8 的 DNS 查询?

这是完整的代码,以防有人感兴趣。

英文:

I have this small piece of code to explain the codebase I'm trying to test. I've skipped checking errors to make the question short.

func lastCNAME(domain string) (lastCNAME string) {
        ns := "8.8.8.8:53"

        c := dns.Client{}
        m := dns.Msg{}
        m.SetQuestion(domain, dns.TypeA)
        r, _, _ := c.Exchange(&m, ns)
        // Last CNAME
        for _, ans := range r.Answer {
                cname, ok := ans.(*dns.CNAME)
                if ok {
                        lastCNAME = cname.Target
                }
        }
        return lastCNAME
}

What is the best way to mock the dns query to the nameserver 8.8.8.8?

Here is the full code in case anyone's curious.

答案1

得分: 1

你可以为所讨论的函数创建一个接口,并在测试中提供一个存根实现:

package main

import (
	"fmt"

	"github.com/miekg/dns"
)

type LastCnamer interface {
	LastCname(domain string) (lastCname string, err error)
}

type LastCnameResolver string

func (l LastCnameResolver) LastCname(domain string) (lastCname string, err error) {
	ns := string(l)

	c := dns.Client{}
	m := dns.Msg{}
	m.SetQuestion(domain, dns.TypeA)
	r, _, err := c.Exchange(&m, ns)
	if err != nil {
		return lastCname, err
	}
	// Last CNAME
	for _, ans := range r.Answer {
		cname, ok := ans.(*dns.CNAME)
		if ok {
			lastCname = cname.Target
		}
	}
	return lastCname, nil
}

type LastCnameStub map[string]string

func (m LastCnameStub) LastCname(domain string) (string, error) {
	return m[domain], nil
}

func main() {
	m := make(map[string]string)
	m["www.linkedin.com."] = "pop-tmu1-alpha.www.linkedin.com."
	var l LastCnamer = LastCnameStub(m)
	cname, _ := l.LastCname("www.linkedin.com.")
	fmt.Println("Stub", cname)

	l = LastCnameResolver("8.8.8.8:53")
	cname, err := l.LastCname("www.linkedin.com.")
	if err != nil {
		panic(err)
	}
	fmt.Println("Resolved", cname)
}

或者,你可以使所讨论的 DNS IP 可配置,以便在测试中进行交换,并启动一个本地 DNS 服务器(github.com/miekg/dns 包中有一个服务器),但这将涉及更多的代码,包括选择一个随机的空闲端口并在测试中使用它。

英文:

You could create an interface for the func in question and provide a stubbed implementation in testing:

package main
import (
"fmt"
"github.com/miekg/dns"
)
type LastCnamer interface {
LastCname(domain string) (lastCname string, err error)
}
type LastCnameResolver string
func (l LastCnameResolver) LastCname(domain string) (lastCname string, err error) {
ns := string(l)
c := dns.Client{}
m := dns.Msg{}
m.SetQuestion(domain, dns.TypeA)
r, _, err := c.Exchange(&m, ns)
if err != nil {
return lastCname, err
}
// Last CNAME
for _, ans := range r.Answer {
cname, ok := ans.(*dns.CNAME)
if ok {
lastCname = cname.Target
}
}
return lastCname, nil
}
type LastCnameStub map[string]string
func (m LastCnameStub) LastCname(domain string) (string, error) {
return m[domain], nil
}
func main() {
m := make(map[string]string)
m["www.linkedin.com."] = "pop-tmu1-alpha.www.linkedin.com."
var l LastCnamer = LastCnameStub(m)
cname, _ := l.LastCname("www.linkedin.com.")
fmt.Println("Stub", cname)
l = LastCnameResolver("8.8.8.8:53")
cname, err := l.LastCname("www.linkedin.com.")
if err != nil {
panic(err)
}
fmt.Println("Resolved", cname)
}

Or you make the DNS IP in question configurable so it can be exchanged in testing and start a local DNS server (there's a server in the github.com/miekg/dns package), but that would be some more code including selecting a random free port and using that in the tests.

huangapple
  • 本文由 发表于 2017年6月30日 17:21:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/44842960.html
匿名

发表评论

匿名网友

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

确定