Comments (9)
@apexskier Feature
is now public on the v3
branch actually after we added the ListFeatures() function. I wrote a quick hacky version of a FakeUnleash for someone so I can share that here. It creates a fake server instead of mocking the client so might not be what you are looking for, but maybe it helps:
package unleash
import (
"encoding/json"
"github.com/Unleash/unleash-client-go/v3/api"
"net/http"
"net/http/httptest"
"sync"
"time"
)
type FakeUnleashServer struct {
sync.RWMutex
srv *httptest.Server
features map[string]bool
}
func (f *FakeUnleashServer) Url() string {
return f.srv.URL
}
func (f *FakeUnleashServer) Enable(feature string) {
f.setEnabled(feature, true)
}
func (f *FakeUnleashServer) Disable(feature string) {
f.setEnabled(feature, false)
}
func (f *FakeUnleashServer) setEnabled(feature string, enabled bool) {
f.Lock()
wasEnabled := f.features[feature]
if enabled != wasEnabled {
f.features[feature] = enabled
}
f.Unlock()
}
func (f *FakeUnleashServer) IsEnabled(feature string) bool {
f.RLock()
enabled := f.features[feature]
f.RUnlock()
return enabled
}
func (f *FakeUnleashServer) setAll(enabled bool) {
for k := range f.features {
f.setEnabled(k, enabled)
}
}
func (f *FakeUnleashServer) EnableAll() {
f.setAll(true)
}
func (f *FakeUnleashServer) DisableAll() {
f.setAll(false)
}
func (f *FakeUnleashServer) handler(w http.ResponseWriter, req *http.Request) {
switch req.Method + " " + req.URL.Path {
case "GET /client/features":
features := []api.Feature{}
for k, v := range f.features {
features = append(features, api.Feature{
Name: k,
Enabled: v,
Strategies: []api.Strategy{
{
Id: 0,
Name: "default",
},
},
CreatedAt: time.Time{},
})
}
res := api.FeatureResponse{
Response: api.Response{Version: 2},
Features: features,
}
dec := json.NewEncoder(w)
if err := dec.Encode(res); err != nil {
println(err.Error())
}
case "POST /client/register":
fallthrough
case "POST /client/metrics":
w.WriteHeader(200)
default:
w.Write([]byte("Unknown route"))
w.WriteHeader(500)
}
}
func NewFakeUnleash() *FakeUnleashServer {
faker := &FakeUnleashServer{
features: map[string]bool{},
}
faker.srv = httptest.NewServer(http.HandlerFunc(faker.handler))
return faker
}
The way it works is that you create call NewFakeUnleash()
to get an instance of the fake server and pass the URL of this server to your unleash client. You then toggle features on the server by calling Enable()
and Disable()
.
from unleash-client-go.
@yofriadi I'm not sure what you mean by not compatible
Here's a quick example of configuring your client to talk to the fake server:
func TestFakeUnleashServer(t *testing.T) {
faker := unleash.NewFakeUnleash()
unleash.Initialize(
unleash.WithListener(&unleash.DebugListener{}),
unleash.WithAppName("my-application"),
unleash.WithUrl(faker.Url()),
unleash.WithRefreshInterval(1*time.Millisecond),
)
unleash.WaitForReady()
faker.Enable("foo")
<-time.After(5 * time.Millisecond) // wait until client refreshes
if unleash.IsEnabled("foo") != true {
t.Errorf("expected IsEnabled to be true")
}
faker.Disable("foo")
<-time.After(5 * time.Millisecond) // wait until client refreshes
if unleash.IsEnabled("foo") != false {
t.Errorf("expected IsEnabled to be false")
}
}
from unleash-client-go.
That would be nice. What do you think @jrbarron ?
from unleash-client-go.
This is the first I've heard of it so no plans yet, but it sounds like a good idea. This will probably involve some refactoring internally since both the repository and the metrics stuff should be abstracted into interfaces so we can stub out the network behavior.
I haven't had much free time lately and the time I have spent on Unleash has been adding support for v4 and variants so if someone else would like to take a stab at this, they are certainly welcome. Otherwise I will try to find some time after I finish the v4 changes.
from unleash-client-go.
Thanks for the feedback. Do you guys have any recommendations on unit testing in general? Do you guys set up an httptest handler's to mock unleash responses?
from unleash-client-go.
@jrmullins I have used a library called gock for mocking the http traffic in the Unleash.
from unleash-client-go.
From my perspective, the easiest way to make this package mockable would be to allow defining a custom storage implementation that we can mock the results of. WithStorage
is already public, but it's not usable because the repository requires it's return data to be of type api.Feature
, which is in an internal package and can't be used by consumers. If Feature
was public, this would be much easier.
https://play.golang.org/p/KIr8rYKTjUD
from unleash-client-go.
@jrbarron Thanks! This ended up allowing us to mock unleash in tests; everything's working well now.
from unleash-client-go.
hi @jrbarron could we have some example implementation for mocking using FakeUnleashServer
because as far as I can try, type FakeUnleashServer
is not compatible with type unleash.Client
, or maybe I am missing something here, thankyou
from unleash-client-go.
Related Issues (20)
- Is there a way to get all the feature flags for a project, not just one at a time? HOT 2
- Proposal: be more strict about WithListener HOT 4
- Implement Global Segments
- (Feature Request) Enable passing api.Feature instead of a string to an alternative of IsEnabled HOT 12
- Update link to GoDoc HOT 2
- feat: add support for fallback function
- failing spec tests HOT 1
- Library flexibility HOT 4
- Unleash client go efficiency HOT 6
- feat: FlexibleRollout should support "custom" stickiness.
- feat: Custom stickiness for variants HOT 1
- Features read from file cannot be cast to Feature HOT 2
- Unable to get latest changes with go.mod HOT 2
- Expose admin API HOT 1
- fix: GetVariant does not accept custom context HOT 1
- Publicly expose the default Strategies for faster and more advanced Strategies. HOT 2
- Unleash context in readme direct to 404 HOT 1
- Why is not options passed when calling GetVariant? HOT 1
- Missing testdata results in failed build HOT 3
- Not able to set Environment in Client HOT 11
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from unleash-client-go.