英文:
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
?
答案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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论