Beispiel #1
0
func main() {

	app := Application{}

	/*
		This is the first of three `inj` API calls. (The others are `inj.Assert()` and `inj.Inject`, more on those
		later). `inj.Provide()` is a variadic function that takes any number of `interface{}`s and inserts then into
		a list of globally-available objects call the application graph.

		After each call to `inj.Provide()`, the graph is 'connected', meaning that any structs with depdendencies (that
		is, structs containing fields with `inj:""` tags) have their dependent fields assigned to nodes on the graph.
		This how how we'll assign values to the three fields of the `Application` struct.

		You can call `inj.Provide()` as many times as you like, which means that it's possible to build a cascade of
		dependencies from imported packages using the `init()` function. Be careful with that, because `inj.Provide()`
		is where all the heavy lifting is done, and it's not fast enough to execute for each request or operation.
		Generally it should be called at startup, like we're doing here.
	*/
	inj.Provide(

		// A pointer to our `Application` is necessary to fulfil its depdendencies. (It must be a pointer so the values
		// can be assigned).
		&app,

		// Objects are stored in the graph, even if they're stored anywhere else. Here we're creating a channel.
		make(ExitChan),

		// The same with the `Config` struct; just create a new instance for the graph and move on.
		&Config{},

		// As noted above, `Logger` happens to match the signature of `fmt.Printf`, so we use that.
		fmt.Printf,

		// This is that 'Hello, I love %s' writer. `Application` doesn't use it, but other graph-dependent functions do.
		WriteResponse,
	)

	/*
		Once you've made all your calls to `inj.Provide()`, it's time to make sure that all the dependencies were met. In
		`inj`, that's fairly simple: use the `inj.Assert()` function. It returns a boolean and a slice of strings. If the
		boolean is false, then the slice will be populated with all the errors that occured during struct injection.
	*/
	if valid, messages := inj.Assert(); !valid {
		fmt.Println(messages)
		os.Exit(1)
	}

	/*
		If we get to this point, we know that `app` has had all its dependencies met, so we can call `app.run()`.
	*/
	app.run()
}
Beispiel #2
0
func main() {
	// Wont work if GOPATH contains multiple DIRs
	path := filepath.Join(os.Getenv("GOPATH"), "src/github.com/adrianduke/configr/examples/simple-json-inj/config.json")
	configr.AddSource(configr.NewFile(path))

	if err := configr.Parse(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	email := Email{}
	inj.Provide(&email)                     // Informs inj to perform DI on given instance
	inj.AddDatasource(configr.GetConfigr()) // Provides inj with a datasource to query

	if valid, errors := inj.Assert(); !valid { // Triggers the inj DI process
		fmt.Println(errors)
		os.Exit(1)
	}

	fmt.Println("> Email Address:", email.FromAddress)
	fmt.Println("> Subject:", email.Subject)
	fmt.Println("> Max Retries:", email.MaxRetries)
	fmt.Println("> Retry on Fail:", email.RetryOnFail)
}
Beispiel #3
0
/*
This is the main test: add all the dependencies to the global graph and run the
application. We can use the http package from the standard library to make sure
the responses from the server are correct, and shut down the server properly when
we're done.
*/
func Test_Application(t *testing.T) {

	app := Application{}
	exit := make(ExitChan)

	// Set up the graph, much the same was as in main.go – and exactly as in the test
	// above, only this time globally
	inj.Provide(
		&app,              // This time it is a pointer
		exit,              // `ExitChan`, this time shared
		&MockConfig{},     // Use the mock config
		MockLogger,        // `Logger`, as above
		MockWriteResponse, // Our specialised response writer
		t,                 // Pointer to `testing.T`, which is now going to be used
	)

	// Make sure everything was loaded properly again
	if valid, messages := inj.Assert(); !valid {
		t.Fatalf("inj.Assert() failed: %s", messages)
	}

	// Run the application in its own goroutine. It should stay running until it's explicitly
	// shut down
	go app.run()

	// Here we make some requests to the application, and check the responses. Again, there are
	// better ways to choose test strings
	tests := []string{
		"fulfilment",
		"doubt",
		"futility",
		"inetivatable narrative hijacking",
	}

	for _, input := range tests {

		res, err := http.Get(fmt.Sprintf("http://localhost:%d/%s", MOCK_HTTP_PORT, input))

		if err != nil {
			t.Fatalf("http.Get(): %s", err)
		}

		body, err := ioutil.ReadAll(res.Body)
		res.Body.Close()

		if err != nil {
			log.Fatal(err)
			t.Fatalf("ioutil.ReadAll %s", err)
		}

		t.Logf("Testing %s...", input)

		if g, e := res.StatusCode, 200; g != e {
			t.Errorf("Expected status code %d, got %d", g, e)
		}

		if g, e := string(body), input; g != e {
			t.Fatalf("Got %s, expected %s")
		}
	}

	// Kill the app
	exit <- struct{}{}
}