Skip to content
This repository has been archived by the owner on Mar 22, 2019. It is now read-only.

Added the ability to override non-zero values #15

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Commits on Oct 26, 2017

  1. Added the ability to override non-zero values

    Previously, if some subtree of an object that was to be populated
    was not zero/nil, we would terminate the population of that subtree
    then and there. However this makes the package hard to use for very
    target dependencies that only occur at the bottom of the dependency
    tree (e.g: a network client or database layer).
    
    With this patch, the injection does move downwards and populate the
    fields that it can.
    
    Furthermore, we can now have constructors populate our structs with
    default values, that will then be overridden by the injection
    mechanism if the tag `inject:"override"` is present on the field.
    This means that we can now use sane defaults when creating our objects
    that we can inject mocks for during unit tests.
    ```go
    // A is our bogus wrapper of the http.Client
    type A struct {
        Client *http.Client `inject:"override"`
    }
    
    // NewA returns a fully functional A, with a non-nil http client.
    func NewA() *A {
        return &A{
            Client: &http.Client{}
        }
    }
    
    var testClient *http.Client
    
    func TestMain(m *testing.M)
        testClient = NewTestClient()
        os.Exit(m.Run())
    }
    
    func TestWithBogusClient(t *testing.T) {
        a := NewA()
        inject.Populate(a, testClient)
    
        // Here the injector should have overridden the default http client
        // inside A to use the bogus client.
        a.Do(...)
    }
    ```
    
    The last feature that I was looking for was the traversal of non-nil
    interfaces. For instance:
    ```go
    // I is our bogus interface. It has no functions for the sake of
    // brevity.
    type I interface {}
    
    // A implements that bogus interface
    type A struct {
        Client *http.Client `inject:""`
    }
    
    // Nested contains an I which does not need to be injected. However,
    // the I (which will be of type A at runtime) needs to be traversed so that
    // we can inject the right *http.Client.
    type Nested struct {
        Iface I
    }
    
    func main() {
        n := &Nested{
            Iface: &A{},
        }
        specialclient := &http.Client{}
        inject.Populate(n, specialclient)
    }
    ```
    This is useful in bigger projects when you have many subcomponents that
    use an *http.Client or sub-interface of that, and need to all have that
    client mocked during unit tests.
    apourchet committed Oct 26, 2017
    Configuration menu
    Copy the full SHA
    b5c69fa View commit details
    Browse the repository at this point in the history