|
| 1 | +// This sample test demonstrates how to mock client HTTP calls. |
| 2 | +package listing02 |
| 3 | + |
| 4 | +import ( |
| 5 | + "encoding/xml" |
| 6 | + "fmt" |
| 7 | + "net/http" |
| 8 | + "net/http/httptest" |
| 9 | + "testing" |
| 10 | +) |
| 11 | + |
| 12 | +const succeed = "\u2713" |
| 13 | +const failed = "\u2717" |
| 14 | + |
| 15 | +var feed = `<?xml version="1.0" encoding="UTF-8"?> |
| 16 | +<rss xmlns:atom="http://www.w3.org/2005/Atom" |
| 17 | + xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" |
| 18 | + xmlns:blogger="http://schemas.google.com/blogger/2008" |
| 19 | + xmlns:georss="http://www.georss.org/georss" |
| 20 | + xmlns:gd="http://schemas.google.com/g/2005" |
| 21 | + xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"> |
| 22 | +<channel> |
| 23 | + <atom:id>tag:blogger.com,1999:blog-6298089572270107210</atom:id> |
| 24 | + <lastBuildDate>Mon, 27 Apr 2015 12:42:23 +0000</lastBuildDate> |
| 25 | + <title>Going Go Programming</title> |
| 26 | + <description>Golang For The Common Man : https://github.com/goinggo</description> |
| 27 | + <link>http://www.goinggo.net/</link> |
| 28 | + <managingEditor>noreply@blogger.com (William Kennedy)</managingEditor> |
| 29 | + <generator>Blogger</generator> |
| 30 | + <openSearch:totalResults>67</openSearch:totalResults> |
| 31 | + <openSearch:startIndex>1</openSearch:startIndex> |
| 32 | + <openSearch:itemsPerPage>25</openSearch:itemsPerPage> |
| 33 | + <item> |
| 34 | + <guid isPermaLink="false">tag:blogger.com,1999:blog-6298089572270107210.post-3707264680032475251</guid> |
| 35 | + <pubDate>Sun, 15 Mar 2015 15:04:00 +0000</pubDate> |
| 36 | + <atom:updated>2015-03-15T11:21:09.934-04:00</atom:updated> |
| 37 | + <title>Object Oriented Programming Mechanics</title> |
| 38 | + <description><div class="p1">Go is an object oriented programming language. It may not have inheritance, but in this 20 minute video from the Bangalore meetup, I will show you how object oriented programming practices and techniques can be applied to your Go programs. From an object oriented standpoint, Go does provides the ability to add behavior to your types via methods, allows you to implement polymorphic behavior via interfaces and gives you a way to extend the state and behavior of any existing type via type embedding. Go also provides a form of encapsulation that allows your types, including their fields and methods, to be visible or invisible. Everything you need to write object oriented programs is available in Go.</div><br /><iframe allowfullscreen="" frameborder="0" height="510" src="https://www.youtube.com/embed/gRpUfjTwSOo" width="100%"></iframe> <br /><b><br /></b><b>Example 1 - Methods: </b><br /><a href="http://play.golang.org/p/hfRkC6nKag" target="_blank">http://play.golang.org/p/hfRkC6nKag</a><br /><br /><b>Example 2 - Interfaces:</b><br /><a href="http://play.golang.org/p/F1UyKlTh3k" target="_blank">http://play.golang.org/p/F1UyKlTh3k</a><br /><br /><b>Example 3 - Extending Types:</b><br /><a href="http://play.golang.org/p/JJ811lBwoz" target="_blank">http://play.golang.org/p/JJ811lBwoz</a><br /><br /><b>Example 4 - Overriding Inner Types:</b><br /><a href="http://play.golang.org/p/-xQFBv9_82" target="_blank">http://play.golang.org/p/-xQFBv9_82</a></description> |
| 39 | + <link>http://www.goinggo.net/2015/03/object-oriented-programming-mechanics.html</link> |
| 40 | + <author>noreply@blogger.com (William Kennedy)</author> |
| 41 | + <media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/gRpUfjTwSOo/default.jpg" height="72" width="72"/> |
| 42 | + <thr:total>0</thr:total> |
| 43 | + </item> |
| 44 | +</channel> |
| 45 | +</rss>` |
| 46 | + |
| 47 | +// Item defines the fields associated with the item tag in |
| 48 | +// the buoy RSS document. |
| 49 | +type Item struct { |
| 50 | + XMLName xml.Name `xml:"item"` |
| 51 | + PubDate string `xml:"pubDate"` |
| 52 | + Title string `xml:"title"` |
| 53 | + Description string `xml:"description"` |
| 54 | + Link string `xml:"link"` |
| 55 | + GUID string `xml:"guid"` |
| 56 | + GeoRssPoint string `xml:"georss:point"` |
| 57 | +} |
| 58 | + |
| 59 | +// Image defines the fields associated with the image tag in |
| 60 | +// the buoy RSS document. |
| 61 | +type Image struct { |
| 62 | + XMLName xml.Name `xml:"image"` |
| 63 | + URL string `xml:"url"` |
| 64 | + Title string `xml:"title"` |
| 65 | + Link string `xml:"link"` |
| 66 | +} |
| 67 | + |
| 68 | +// Channel defines the fields associated with the channel tag in |
| 69 | +// the buoy RSS document. |
| 70 | +type Channel struct { |
| 71 | + XMLName xml.Name `xml:"channel"` |
| 72 | + Title string `xml:"title"` |
| 73 | + Description string `xml:"description"` |
| 74 | + Link string `xml:"link"` |
| 75 | + PubDate string `xml:"pubDate"` |
| 76 | + LastBuildDate string `xml:"lastBuildDate"` |
| 77 | + TTL string `xml:"ttl"` |
| 78 | + Language string `xml:"language"` |
| 79 | + ManagingEditor string `xml:"managingEditor"` |
| 80 | + WebMaster string `xml:"webMaster"` |
| 81 | + Image Image `xml:"image"` |
| 82 | + Items []Item `xml:"item"` |
| 83 | +} |
| 84 | + |
| 85 | +// Document defines the fields associated with the buoy RSS document. |
| 86 | +type Document struct { |
| 87 | + XMLName xml.Name `xml:"rss"` |
| 88 | + Channel Channel `xml:"channel"` |
| 89 | + URI string |
| 90 | +} |
| 91 | + |
| 92 | +// mockServer returns a pointer to a server to handle the mock get call. |
| 93 | +func mockServer() *httptest.Server { |
| 94 | + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 95 | + w.WriteHeader(200) |
| 96 | + w.Header().Set("Content-Type", "application/xml") |
| 97 | + fmt.Fprintln(w, feed) |
| 98 | + })) |
| 99 | + return server |
| 100 | +} |
| 101 | + |
| 102 | +// TestDownload tests if download web content is working. |
| 103 | +func TestDownload(t *testing.T) { |
| 104 | + server := mockServer() |
| 105 | + defer server.Close() |
| 106 | + |
| 107 | + t.Log("Given the need to test downloading content.") |
| 108 | + { |
| 109 | + resp, err := http.Get(server.URL) |
| 110 | + if err == nil { |
| 111 | + t.Log("\tShould be able to make the Get call.", |
| 112 | + succeed) |
| 113 | + } else { |
| 114 | + t.Fatal("\tShould be able to make the Get call.", |
| 115 | + failed, err) |
| 116 | + } |
| 117 | + |
| 118 | + defer resp.Body.Close() |
| 119 | + |
| 120 | + if resp.StatusCode == 200 { |
| 121 | + t.Log("\tShould receive a \"200\" status code.", |
| 122 | + succeed) |
| 123 | + } else { |
| 124 | + t.Error("\tShould receive a \"200\" status code.", |
| 125 | + failed, resp.StatusCode) |
| 126 | + } |
| 127 | + |
| 128 | + var d Document |
| 129 | + if err := xml.NewDecoder(resp.Body).Decode(&d); err == nil { |
| 130 | + t.Log("\tShould be able to unmarshal the response.", |
| 131 | + succeed) |
| 132 | + } else { |
| 133 | + t.Fatal("\tShould be able to unmarshal the response.", |
| 134 | + failed, err) |
| 135 | + } |
| 136 | + |
| 137 | + if len(d.Channel.Items) == 1 { |
| 138 | + t.Log("\tShould have \"1\" item in the feed.", |
| 139 | + succeed) |
| 140 | + } else { |
| 141 | + t.Fatal("\tShould have \"1\" item in the feed.", |
| 142 | + failed, len(d.Channel.Items)) |
| 143 | + } |
| 144 | + } |
| 145 | +} |
0 commit comments