I don't know how to test the http response given in the code below.
func getVolDetails(volName string, obj interface{}) error {
addr := os.Getenv("MAPI_ADDR")
if addr == "" {
err := errors.New("MAPI_ADDR environment variable not set")
fmt.Println(err)
return err
}
url := addr + "/path/to/somepage/" + volName
client := &http.Client{
Timeout: timeout,
}
resp, err := client.Get(url)
if resp != nil {
if resp.StatusCode == 500 {
fmt.Printf("VSM %s not found\n", volName)
return err
} else if resp.StatusCode == 503 {
fmt.Println("server not reachable")
return err
}
} else {
fmt.Println("server not reachable")
return err
}
if err != nil {
fmt.Println(err)
return err
}
defer resp.Body.Close()
return json.NewDecoder(resp.Body).Decode(obj)
}
With the help of some references i wrote unit test for this which is given below
func TestGetVolDetails(t *testing.T) {
var (
volume v1.Volume
server *httptest.Server
)
tests := map[string]struct {
volumeName string
err error
}{
"TestOne": {"vol", nil},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
response := `{"metadata":{"annotations":{"vsm.openebs.io/targetportals":"10.98.65.136:3260","vsm.openebs.io/cluster-i ps":"10.98.65.136","openebs.io/jiva-iqn":"iqn.2016-09.com.openebs.jiva:vol","deployment.kubernetes.io/revision":"1","openebs.io/storage-pool" :"default","vsm.openebs.io/replica-count":"1","openebs.io/jiva-controller-status":"Running","openebs.io/volume-monitor":"false","openebs.io/r eplica-container-status":"Running","openebs.io/jiva-controller-cluster-ip":"10.98.65.136","openebs.io/jiva-replica-status":"Running","vsm.ope nebs.io/iqn":"iqn.2016-09.com.openebs.jiva:vol","openebs.io/capacity":"2G","openebs.io/jiva-controller-ips":"10.36.0.6","openebs.io/jiva-repl ica-ips":"10.36.0.7","vsm.openebs.io/replica-status":"Running","vsm.openebs.io/controller-status":"Running","openebs.io/controller-container- status":"Running","vsm.openebs.io/replica-ips":"10.36.0.7","openebs.io/jiva-target-portal":"10.98.65.136:3260","openebs.io/volume-type":"jiva ","openebs.io/jiva-replica-count":"1","vsm.openebs.io/volume-size":"2G","vsm.openebs.io/controller-ips":"10.36.0.6"},"creationTimestamp":null ,"labels":{},"name":"vol"},"status":{"Message":"","Phase":"Running","Reason":""}}`
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, response)
}))
os.Setenv("MAPI_ADDR", "http://"+server.URL)
if got := GetVolDetails(tt.volumeName, &volume); got != tt.err {
t.Fatalf("GetVolDetails(%v) => got %v, want %v ", tt.volumeName, got, tt.err)
}
defer server.Close()
})
}
}
Where response is the response i'm getting from the server. This gives me always different errors.
got invalid character '<' looking for beginning of value, want <nil>
got Get http://www.HugeDomains.com: net/http: request canceled (Client.Timeout exceeded while awaiting headers), want <nil>
What am I doing wrong?
Edit:
Updated the code with SOME_ADDR to MAPI_ADDR which was done while posting question. Please don't be confused with that, problem remains as it is.
You are getting a timeout but you are not specifying what timeout is set to. I suspect that this is not a time.Duration object and that is causing your timeout. There are a few other issues as well. To get this to work I did:
Change the function being called in the test to getVolDetails to match the code (not the lower case g)
Set the Timeout when creating the client to Timeout: time.Second * 10
Remove the "http://"+ from the os.Setenv("MAPI_ADDR", "http://"+server.URL) line
Corrected code is:
var timeout time.Duration = time.Second * 1000
func getVolDetails(volName string, obj interface{}) error {
addr := os.Getenv("MAPI_ADDR")
if addr == "" {
err := errors.New("MAPI_ADDR environment variable not set")
fmt.Println(err)
return err
}
url := addr + "/path/to/somepage/" + volName
client := &http.Client{
Timeout: timeout,
}
resp, err := client.Get(url)
if resp != nil {
if resp.StatusCode == 500 {
fmt.Printf("VSM %s not found\n", volName)
return err
} else if resp.StatusCode == 503 {
fmt.Println("server not reachable")
return err
}
} else {
fmt.Println("server not reachable")
return err
}
if err != nil {
fmt.Println(err)
return err
}
defer resp.Body.Close()
return json.NewDecoder(resp.Body).Decode(obj)
}
and test:
func TestGetVolDetails(t *testing.T) {
var (
volume v1.Volume
server *httptest.Server
)
tests := map[string]struct {
volumeName string
err error
}{
"TestOne": {"vol", nil},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
response := `{"metadata":{"annotations":{"vsm.openebs.io/targetportals":"10.98.65.136:3260","vsm.openebs.io/cluster-i ps":"10.98.65.136","openebs.io/jiva-iqn":"iqn.2016-09.com.openebs.jiva:vol","deployment.kubernetes.io/revision":"1","openebs.io/storage-pool" :"default","vsm.openebs.io/replica-count":"1","openebs.io/jiva-controller-status":"Running","openebs.io/volume-monitor":"false","openebs.io/r eplica-container-status":"Running","openebs.io/jiva-controller-cluster-ip":"10.98.65.136","openebs.io/jiva-replica-status":"Running","vsm.ope nebs.io/iqn":"iqn.2016-09.com.openebs.jiva:vol","openebs.io/capacity":"2G","openebs.io/jiva-controller-ips":"10.36.0.6","openebs.io/jiva-repl ica-ips":"10.36.0.7","vsm.openebs.io/replica-status":"Running","vsm.openebs.io/controller-status":"Running","openebs.io/controller-container- status":"Running","vsm.openebs.io/replica-ips":"10.36.0.7","openebs.io/jiva-target-portal":"10.98.65.136:3260","openebs.io/volume-type":"jiva ","openebs.io/jiva-replica-count":"1","vsm.openebs.io/volume-size":"2G","vsm.openebs.io/controller-ips":"10.36.0.6"},"creationTimestamp":null ,"labels":{},"name":"vol"},"status":{"Message":"","Phase":"Running","Reason":""}}`
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, response)
}))
os.Setenv("MAPI_ADDR", server.URL)
if got := getVolDetails(tt.volumeName, &volume); got != tt.err {
t.Fatalf("GetVolDetails(%v) => got %v, want %v ", tt.volumeName, got, tt.err)
}
defer server.Close()
})
}
}
Related
I have the following function:
func CreateByID(w http.ResponseWriter, r *http.Request) {
formFile, _, err := r.FormFile("audio")
if err != nil {
return
}
defer formFile.Close()
defer r.MultipartForm.RemoveAll()
tmpFile, err := os.CreateTemp("/tmp")
if err != nil {
return
}
defer os.Remove(tmpFile.Name())
io.Copy(tmpFile, formFile)
err = validateFile(tmpFile.Name())
if err != nil {
return
}
}
func validateFile(path string) error {
fs, err := os.Stat(path)
if err != nil {
return
}
if fs.Size() < allowedSize {
return fmt.Errorf("file is too small")
}
}
which is basically creating a temp file from the HTTP request and validating it before further processing. This works fine except for the unit test. When I'm testing this function - I'm getting always filesize = 0.
Below you can see the Test case:
func TestCreateByID(t *testing.T) {
pr, pw := io.Pipe()
writer := multipart.NewWriter(pw)
go func() {
defer writer.Close()
_, err := writer.CreateFormFile("audio", "/tmp/audioFile")
if err != nil {
t.Error(err)
}
generateAudioSample("/tmp/audioFile")
}()
request := httptest.NewRequest(http.MethodGet, "/{id}")
request.Header.Add("Content-Type", writer.FormDataContentType())
response := httptest.NewRecorder()
# Calling The Actual Function
CreateByID(response, request)
handler := http.NewServeMux()
handler.ServeHTTP(response, request)
if response.Code != 200 {
t.Errorf("Expected %d, received %d", 200, response.Code)
return
}
}
generateAudioSample function is working fine because I can see the file on the filesystem and its size it bigger than 0 but for some reason this function io.Copy(tmpFile, formFile) doesn't seem to handle FormFile correctly, and is creating just an empty file on the filesystem and obviously fail the test. What else should I add to the test function in order to pass the test?
I'm trying to test a function that tries to establish a TCP connection.
I'm trying to run a test case that should return an error indicating that a certain IP is not reachable.
The code fails if I wait for a certain amount of time, bigger than the timeout specified, or if I try to connect to a port that wouldn't be available.
The failure seems to be in l.Accept() in the tests. The code does not run after that.
The code:
func Run(
trackerInfo tracker.NotCompactGetRequestResponse,
infoHash [20]byte,
) (err error) {
for _, peer := range trackerInfo.Peers {
conn, err := peerTcpConnection(peer.Ip, peer.Port)
if err != nil {
return PeerConnectionError{
Reason: err.Error(),
}
}
defer conn.Close()
handshake := Handshake{
Pstr: "BitTorrent protocol",
InfoHash: infoHash,
PeerId: [20]byte(tracker.GetPeerIdAsByteArray()),
}
serializedHandshake, err := handshake.Serialize()
if err != nil {
return err
}
_, err = conn.Write(serializedHandshake)
if err != nil {
return err
}
}
return nil
}
func peerTcpConnection(url, port string) (conn net.Conn, err error) {
address := fmt.Sprintf("%v:%v", url, port)
return net.DialTimeout("tcp", address, peerTimeout) // 3 * time.Second
}
The test:
func TestRun(t *testing.T) {
// t.Parallel()
testCases := getTestCases()
for _, testCase := range testCases {
testCase := testCase
t.Run(testCase.name, func(t *testing.T) {
// t.Parallel()
errChannel := make(chan error)
go func() {
fmt.Println(fmt.Sprintf("1 -> %v", time.Now()))
errChannel <- download.Run(testCase.trackerInfo, testCase.infoHash)
fmt.Println(fmt.Sprintf("2 -> %v", time.Now()))
}()
l, conn := getTestConnection(t, testCase.trackerInfo.Peers[0].Port)
defer func() {
err := conn.Close()
if err != nil {
t.Fatal(err)
}
err = l.Close()
if err != nil {
t.Fatal(err)
}
}()
err := <-errChannel
if !errors.Is(err, testCase.expectedErr) {
t.Errorf(
"got error '%v', expected error '%v'",
err,
testCase.expectedErr,
)
}
var buffer []byte
buffer, err = ioutil.ReadAll(conn)
if err != nil {
t.Fatal(err)
}
receivedHandshake := download.Handshake{}
receivedHandshake.Deserialize(buffer)
if !download.CompareHandshakes(receivedHandshake, testCase.expectedHandshake) {
t.Errorf(
"got handshake '%v', expected handshake '%v'",
err,
testCase.expectedHandshake,
)
}
})
}
}
func getTestConnection(t *testing.T, port string) (l net.Listener, conn net.Conn) {
if port == "34568" {
// portN, err := strconv.Atoi(port)
// if err != nil {
// t.Fatal(err)
// }
// port = fmt.Sprint(portN + 1)
time.Sleep(4 * time.Second)
}
l, err := net.Listen("tcp", fmt.Sprintf(":%v", port))
if err != nil {
t.Fatal(err)
}
fmt.Println(fmt.Sprintf("3 -> %v", time.Now()))
conn, err = l.Accept()
fmt.Println(fmt.Sprintf("4 -> %v", time.Now()))
if err != nil {
t.Fatal(err)
}
return l, conn
}
The result:
=== RUN TestRun
=== RUN TestRun/successful_download
1 -> 2022-03-16 15:31:04.542987703 +0000 UTC m=+0.000510682
3 -> 2022-03-16 15:31:04.543043416 +0000 UTC m=+0.000566399
4 -> 2022-03-16 15:31:04.543208564 +0000 UTC m=+0.000731539
2 -> 2022-03-16 15:31:04.543257141 +0000 UTC m=+0.000780117
=== RUN TestRun/unsuccessful_download_-_cannot_connect_to_peer
1 -> 2022-03-16 15:31:04.543331399 +0000 UTC m=+0.000854375
3 -> 2022-03-16 15:31:08.543806112 +0000 UTC m=+4.001329160
I'm currently trying to send a POST request to an external API from a GCP Cloud Function. I've tested the function extensively locally and it fulfills the request every time and also works from Postman, but when I run the exact same code from within a cloud function, it returns a 500 from the external API every single time.
I'm genuinely at a loss as to why when sending the POST request from within the cloud function it fails every single time.
Does GCP add any headers that might interfere with an external API call or is there a configuration option within the cloud function settings that needs to be configured to allow an external POST request?
I've attempted to implement an http retry mechanism, but that did not work either.
Again, locally and from Postman, the exact same code is successful every time I run it.
Here is the code I use to generate and send the request:
package email
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/hashicorp/go-retryablehttp"
)
var FailedRequestErr = errors.New("failed request to moosend")
const (
successCode = 0
moosendHost = "api.moosend.com/v3"
dailyNewsletterMailingListID = "2e461f4c-99d1-4a8e-80ea-168b20bdaf5f"
mainEmail = "jason#functionalbits.io"
campaignNameBase = "Functional Bits Newsletter - Issue"
campaignSubjectBase = "Functional Bits Issue"
)
type CreatingADraftCampaignRequest struct {
Name string `json:"Name"`
Subject string `json:"Subject"`
SenderEmail string `json:"SenderEmail"`
ReplyToEmail string `json:"ReplyToEmail"`
IsAB string `json:"IsAB"`
ConfirmationToEmail string `json:"ConfirmationToEmail,omitempty"`
WebLocation string `json:"WebLocation,omitempty"`
MailingLists []MailingLists `json:"MailingLists,omitempty"`
SegmentID string `json:"SegmentID,omitempty"`
ABCampaignType string `json:"ABCampaignType,omitempty"`
TrackInGoogleAnalytics string `json:"TrackInGoogleAnalytics,omitempty"`
DontTrackLinkClicks string `json:"DontTrackLinkClicks,omitempty"`
SubjectB string `json:"SubjectB,omitempty"`
WebLocationB string `json:"WebLocationB,omitempty"`
SenderEmailB string `json:"SenderEmailB,omitempty"`
HoursToTest string `json:"HoursToTest,omitempty"`
ListPercentage string `json:"ListPercentage,omitempty"`
ABWinnerSelectionType string `json:"ABWinnerSelectionType,omitempty"`
}
type MailingLists struct {
MailingListID string `json:"MailingListId"`
SegmentID float64 `json:"SegmentId,omitempty"`
}
type CampaignResponse struct {
Code int32 `json:"Code"`
Err interface{} `json:"Error"`
Context interface{} `json:"Context"`
}
type MoosendAPI struct {
apiKey string
client *http.Client
}
func NewMoosendAPI(apiKey string) *MoosendAPI {
retryClient := retryablehttp.NewClient()
retryClient.RetryMax = 5
standardClient := retryClient.StandardClient()
return &MoosendAPI{
apiKey: apiKey,
client: standardClient,
}
}
func (m *MoosendAPI) CreateDraftCampaign(issueNumber string, webLocation string) (*CampaignResponse, error) {
campaign := CreatingADraftCampaignRequest{
Name: fmt.Sprintf("%s %s", campaignNameBase, issueNumber),
Subject: fmt.Sprintf("%s %s", campaignSubjectBase, issueNumber),
IsAB: "false",
WebLocation: webLocation,
MailingLists: []MailingLists{{MailingListID: dailyNewsletterMailingListID}},
SenderEmail: mainEmail,
ReplyToEmail: mainEmail,
ConfirmationToEmail: mainEmail,
TrackInGoogleAnalytics: "true",
}
body, err := json.Marshal(&campaign)
if err != nil {
log.Println("error marshalling campaign request")
return nil, err
}
fullURL := fmt.Sprintf("https://%s/campaigns/create.json?apikey=%s", moosendHost, m.apiKey)
req, err := http.NewRequest(http.MethodPost, fullURL, bytes.NewBuffer(body))
if err != nil {
log.Println("request error")
return nil, err
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
log.Printf("request: %+v", req)
resp, err := m.client.Do(req)
if resp.StatusCode != http.StatusOK {
return nil, FailedRequestErr
}
if err != nil {
log.Println("error sending request")
return nil, err
}
log.Printf("response: %+v", resp)
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println("error reading response body")
return nil, err
}
var draftResponse CampaignResponse
if err := json.Unmarshal(respBody, &draftResponse); err != nil {
log.Println("error unmarshalling response")
log.Printf("%+v", draftResponse)
return nil, err
}
return &draftResponse, nil
}
func (m *MoosendAPI) SendCampaign(campaignID string) error {
fullURL := fmt.Sprintf("https://%s/campaigns/%s/send.json?apikey=%s", moosendHost, campaignID, m.apiKey)
req, err := http.NewRequest(http.MethodPost, fullURL, nil)
if err != nil {
log.Println("error creating request")
return err
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
resp, err := m.client.Do(req)
if err != nil {
log.Println("error sending request")
return err
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println("error reading response body")
return err
}
var sendResponse CampaignResponse
if err := json.Unmarshal(respBody, &sendResponse); err != nil {
log.Println("error unmarshalling response")
log.Printf("%+v", sendResponse)
return err
}
return nil
}
Then how it's run in the main function code:
package function
import (
"context"
"encoding/json"
"errors"
"log"
"os"
"github.com/Functional-Bits/emailer-service/internal/email"
"github.com/Functional-Bits/emailer-service/internal/publish"
)
func CampaignGenerator(ctx context.Context, m publish.PubSubMessage) error {
moosendAPIKey, ok := os.LookupEnv("MOOSEND_API_KEY")
if !ok {
log.Println("missing moosendAPIKey")
}
mAPI := email.NewMoosendAPI(moosendAPIKey)
var msg publish.IncomingMessage
if err := json.Unmarshal(m.Data, &msg); err != nil {
log.Println(err)
return err
}
log.Printf("received message: %+v", msg)
log.Printf("generating draft campaign for issue %s", msg.IssueNumber)
draftResponse, err := mAPI.CreateDraftCampaign(msg.IssueNumber, msg.FileURL)
if err != nil {
log.Println(err)
return err
}
log.Printf("draft response: %+v", draftResponse)
campaignID, ok := draftResponse.Context.(string)
if !ok {
log.Printf("response didn't contain an ID: %+v", draftResponse)
return errors.New("no campaign generated")
}
log.Printf("sending campgain %s", campaignID)
if err := mAPI.SendCampaign(campaignID); err != nil {
log.Println(err)
return err
}
log.Printf("campaign successfully sent for issue number %s", msg.IssueNumber)
return nil
}
When this code is run locally, It correctly makes the 2 calls and sends an email campaign. When run from the cloud function I get a 500 internal server error with no additional information as to why. Link to API docs.
I get the following response from the external API (from my cloud function logs)
response: &{
Status:500 Internal Server Error
StatusCode:500
Proto:HTTP/1.1
ProtoMajor:1
ProtoMinor:1
Header:map[Access-Control-Allow-Headers:[Content-Type, Accept, Cache-Control, X-Requested-With]
Access-Control-Allow-Methods:[GET, POST, OPTIONS, DELETE, PUT]
Access-Control-Allow-Origin:[*]
Cache-Control:[private]
Content-Length:[12750]
Content-Type:[text/html; charset=utf-8]
Date:[Sun, 12 Dec 2021 07:00:09 GMT]
Server:[Microsoft-IIS/10.0]
X-Aspnet-Version:[4.0.30319]
X-Powered-By:[ASP.NET]
X-Robots-Tag:[noindex, nofollow]
X-Server-Id:[1]]
Body:0xc0003f04c0
ContentLength:12750
TransferEncoding:[]
Close:false
Uncompressed:false
Trailer:map[]
Request:0xc000160b00
TLS:0xc000500630
}
The response causes an unmarshal error because no campaign ID is returned.
I have a simple function which takes a URL and fetches the response:
func getUrl(url string) (string, error) {
var theClient = &http.Client{Timeout: 12 * time.Second}
resp, err := theClient.Get(url)
if err != nil {
return "", err
}
defer r.Body.Close()
body, readErr := ioutil.ReadAll(resp.Body)
if readErr != nil {
return "", readErr
}
return string(body), nil
}
Now, I want to trigger an error on the theClient.Get(url) line but I don't know how to. I can trigger an error on the ReadAll() line, by returning no response but with content-length:2.
How can I trigger an error on the theClient.Get(url) line for my unit test?
func TestGetUrl(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", "2")
}))
defer server.Close()
gotContent, gotErr := getUrl(server.URL)
wantErr := "unexpected EOF"
if gotErr == nil || gotErr.Error() != wantErr {
t.Errorf("got err %v; wanted %s", gotErr, wantErr)
}
}
Easiest way is to simply pass an invalid URL:
_, err := http.Get("clearly not a valid url")
fmt.Println("Got error:", err != nil) // Got error: true
Another option is to make it timeout by sleeping in your httptest.Server handler, but that doesn't seem like a very nice idea (but you will be able to assert that it was called in the first place).
i have just started learning to write unit tests for the http requests, i went through several blogs but i didn't understood how to write tests for this using Ginkgo.
func getVolDetails(volName string, obj interface{}) error {
addr := os.Getenv("SOME_ADDR")
if addr == "" {
err := errors.New("SOME_ADDR environment variable not set")
fmt.Println(err)
return err
}
url := addr + "/path/to/somepage/" + volName
client := &http.Client{
Timeout: timeout,
}
resp, err := client.Get(url)
if resp != nil {
if resp.StatusCode == 500 {
fmt.Printf("VSM %s not found\n", volName)
return err
} else if resp.StatusCode == 503 {
fmt.Println("server not reachable")
return err
}
} else {
fmt.Println("server not reachable")
return err
}
if err != nil {
fmt.Println(err)
return err
}
defer resp.Body.Close()
return json.NewDecoder(resp.Body).Decode(obj)
}
// GetVolAnnotations gets annotations of volume
func GetVolAnnotations(volName string) (*Annotations, error) {
var volume Volume
var annotations Annotations
err := getVolDetails(volName, &volume)
if err != nil || volume.Metadata.Annotations == nil {
if volume.Status.Reason == "pending" {
fmt.Println("VSM status Unknown to server")
}
return nil, err
}
// Skipped some part,not required
}
I went through this blog and it exactly explains what my code requires but it uses Testing package and i want to implement this using ginkgo.
Take a look at ghttp package:
http://onsi.github.io/gomega/#ghttp-testing-http-clients
https://godoc.org/github.com/onsi/gomega/ghttp
A rough sketch might look like:
import (
"os"
. "github.com/onsi/ginkgo/tmp"
"github.com/onsi/gomega/ghttp"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("GetVolAnnotations", func() {
var server *ghttp.Server
var returnedVolume Volume
var statusCode int
BeforeEach(func() {
server = ghttp.NewServer()
os.Setenv("SOME_ADDR", server.Addr())
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/path/to/somepage/VOLUME"),
ghttp.RespondWithJSONEncodedPtr(&statusCode, &returnedVolume),
)
)
})
AfterEach(func() {
server.Close()
})
Context("When when the server returns a volume", func() {
BeforeEach(func() {
returnedVolume = Volume{
Metadata: Metadata{
Annotations: []string{"foo"}
}
}
statusCode = 200
})
It("returns the annotations associated with the volume", func() {
Expect(GetVolAnnotations("VOLUME")).To(Equal([]string{"foo"}))
})
})
Context("when the server returns 500", func() {
BeforEach(func() {
statusCode = 500
})
It("errors", func() {
value, err := GetVolAnnotations("VOLUME")
Expect(value).To(BeNil())
Expect(err).To(HaveOccurred())
})
})
Context("when the server returns 503", func() {
BeforEach(func() {
statusCode = 503
})
It("errors", func() {
value, err := GetVolAnnotations("VOLUME")
Expect(value).To(BeNil())
Expect(err).To(HaveOccurred())
})
})
})
I think you've got a few issues with your code though. If you get a 500 or 503 status code you won't necessarily have an err so you'll need to create and send back a custom error from your server.