我有以下函数,在@poy 的帮助下,我能够为它创建模拟以便对其进行单元测试。
现在的问题是我有包装函数也需要测试
这是原始函数,已经过测试
func httpReq(cc []string, method string, url string) ([]byte, error) {
httpClient := http.Client{}
req, err := http.NewRequest(method, url, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to execute http request")
}
//Here we are passing user and password
req.SetBasicAuth(cc[1], cc[2])
res, err := httpClient.Do(req)
if err != nil {
fmt.error(err)
}
val, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.error(err)
}
defer res.Body.Close()
return val, nil
}
这是按预期工作的测试,此测试使用 https://golang.org/pkg/net/http/httptest/为了模拟 http 请求。
func Test_httpReq(t *testing.T){
expectedValue = "some-value"
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
u,p,ok := r.BasicAuth()
if !ok || u != "fakeuser" || p != "fakepassword" {
t.Fatal("wrong auth")
}
w.Write([]byte(expectedValue))
})
val, err := httpReq(
[]string{"fakeuser", "fakepassword"},
http.MethodPost,
server.URL,
)
if err != nil{
t.Fatal(err)
}
if val != expectedValue {
t.Fatalf("expected %q to equal %q", val, expectedValue)
}
现在的问题是我还有另一个函数调用上述函数也需要测试。
这是使用 httpReq 的函数,我还需要为它创建测试
func (c *Service) invoke(Connection Connection, args []string) {
service, err := c.getService(Connection, args)
serviceC, err := c.getServiceK(service, []string{"url", “user”, “id”})
c := strings.Fields(serviceC)
//—————Here we are using the http function again
val, err := httpReq(c[1], c[1],”post”, c[0])
if err != nil {
fmt.println(err)
}
fmt.Print(string(val))
}
现在,当我对其进行测试时,我在 http 请求方法 中遇到了错误,因为在这里我无法模拟 http。
Golang 有什么技术可以帮助解决这种情况吗?
我已经搜索过了,比如依赖注入(inject),发现也许接口(interface)可以提供帮助,但由于这是 http,我不确定该怎么做。
任何具有这种背景的例子都会对我很有帮助。
最佳答案
服务对象可以有这样的接口(interface)
type Service struct {
serviceK typeK
serviceHttp serviceHttp // of type interface hence can be mocked
}
普通应用程序代码可以使用实际对象初始化服务。测试将有模拟对象
type Req struct {
}
type Resp struct {
}
type ServiceHttp interface{
HttpReq(params Req)(Resp, error)
}
type Implementation struct {
}
func (i *Implementation)HttpReq(params Req)(Resp, error){
// buid http request
}
func (c *Service) invoke(Connection Connection, args []string) {
service, err := c.getService(Connection, args)
serviceC, err := c.getServiceK(service, []string{"url", “user”, “id”})
c := strings.Fields(serviceC)
serviceImp := c.GetServiceImp()
// init params with the required fields
val, err := c.HttpReq(params)
if err != nil {
fmt.println(err)
}
fmt.Print(string(val))
}
当您运行测试时,您可以使用返回虚拟响应的模拟实现来初始化服务对象。
type MockImplementation struct {
}
func (i *MockImplementation)HttpReq(Resp, error){
// return mock response
}
func TestMain(){
services := {
serviceHttp:MockImplementation{},
serviceK: typeK{}, // initialise this
}
}
这是测试它的方法之一。其他方式可能是我猜 httpReq 返回 http.ResponseWriter 的地方,你可以使用 httptest.ResponseRecorder 来测试它。
关于unit-testing - 以 http 作为包装函数的依赖项的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53801576/
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您
对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一