Hi all,
I'm currently making a package that wraps the client functionality for a web service called diawi. For background, diawi's is a hosting site for mobile apps in development or to be released to a limited audience (Such as testers, clients, etc).
I've completed most of the package and want to begin writing tests for all the functionality and I've hit a (mental) road block, how exactly should I write tests for a client side of a web service?
Looking at upload_test.go
package godiawi
import (
"testing"
)
func TestUploadSuccess(t *testing.T) {
ur := UploadRequest(Token: "APIToken", File: "app.ip"}
uploadResponse, err := ur.upload()
if err != nil {
t.Errorf("Error: %s", err)
}
if uploadResponse.status != Ok {
t.Errorf("Failed to upload app)
}
}
Would this be a bad design since this is dependent on the web service? Since if errors or issues are occurring on diawi's side, it would then report a false-negative in the test cases.
I would like to avoid this but what is the recommended way of making the tests deterministic?
评论:
fvosberg:
fvosberg:I usually do this by first, writing tests against the third party service which consist of more or less a request/expected response pair. This tests I just have to execute while writing it and in the future to verify the API hasn't changed. After that, I write a mock for the external service and use the same tested pairs of request/response. This mock is ready to be used in your test. But that trades only off, when the client itself has logic, I think. You can't test that an external service has not changed it's behavior without relying on it's availability
adelowo:Another good way I've found is this recorder: https://github.com/seborama/govcr I didn't use it yet, but it looks like the thing you need, doesn't it?
sethammons:You should make use of the request recorder https://godoc.org/net/http/httptest#ResponseRecorder
bigpigfoot:Have the client to diawi adhere to an interface. Then you use a fake that adheres to the interface in your tests. You can now test your code against errors and happy path from diawi. Like you said, you don't want to be in a false-negative situation depending on their ability to serve your request. At least, not at the unit level. For integration testing, I think it is fine to make a real call to their service, but this is something that should happen at the end of testing, before deployment.
puffybunion:you should just test your requests (for client) and responses (for server), then proceed to integration tests.
for example, I'd do
func TestUploadRequest(t *testing.T) { req, err := client.UploadRequest(params) if err != nil { t.Error(err) } assert(req) }
Like others have said - you can just use ResponseRecorder.
Another option is mocking an http.Client by defining a Doer/Client interface: https://play.golang.org/p/P8fFoC58Cg
