Skip to content

Commit f478a90

Browse files
authored
testing: Add internal/digtest, DRY up Provide/Invoke checks (#314)
This is a large change, but it's largely mechanical/automated. The non-mechanical changes were in the commit: internal: Add digtest package See #314 for just that commit. The digtest package includes wrappers around `dig.Container` and friends that let us make the following replacments: require.NoError(t, c.Provide(f)) // to c.RequireProvide(f) require.NoError(t, c.Invoke(f)) // to c.RequireInvoke(f) (For a majority of cases, `f` is a large inline function so the 3 levels of nesting really hurts readability.) To make this possible, the commits before introduction of digtest collectively do the following: - For most tests that rely on `dig.New`, move them into a `dig_test` package. This has the effect of making them "external tests". This is necessary because only external tests can import the new `digtest` package. Tests that are in the `dig` package cannot import `digtest` because `digtest` imports `dig`, and that introduces a cyclic dependency. - A number of the external tests rely on private APIs. For cases where the tests are entirely for the private functionality, move them into a `*_int_test.go` file with `package dig`. This file is a regular internal test with access to unexported APIs. - For cases where the target of the test is a public API, but a private API is used for convenience or determinism (the private `setRand` option, for example), export the functionality from a test file with `package dig`. ```go // foo_test.go package dig func SetRand(*math.Rand) Option ``` This exposes that functionality for use from an external test, but does not make it part of our public API. To be clear, this means ```go // bar_test.go package dig_test import ".../dig" func foo() { dig.SetRand(...) } ``` - Several of the tests verify type names with the package name: `dig.A`, `dig.type1`, etc. Regular expressions were applied liberally to turn these into `dig_test.A`, `dig_test.type1`, etc. Finally, following the splitting of tests into external and internal tests, and addition of the digtest helper package, this incorporates digtest into tests by applying the following gopatch patch to all test files and reverting the change to `example_test.go`. ```diff @@ var c expression @@ import "go.uber.org/dig" +import "go.uber.org/dig/internal/digtest" -c := dig.New( +c := digtest.New(t, ..., ) @@ var require identifier var container expression @@ -require.NoError(t, - container.Provide( + container.RequireProvide( ..., + ) - ), - ..., -) @@ var require identifier var container expression @@ -require.NoError(t, - container.Invoke( + container.RequireInvoke( ..., + ) - ), - ..., -) @@ var require identifier var c expression @@ -err := c.Provide( +c.RequireProvide( ...) -require.NoError(t, err, ...) @@ var require identifier var c expression @@ -err := c.Invoke( +c.RequireInvoke( ...) -require.NoError(t, err, ...) ``` The patch largely did its job; a couple compilation had to be fixed manually.
1 parent 29dd172 commit f478a90

23 files changed

+1547
-1298
lines changed

constructor_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright (c) 2022 Uber Technologies, Inc.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
// THE SOFTWARE.
20+
21+
package dig
22+
23+
import (
24+
"testing"
25+
26+
"github.com/stretchr/testify/assert"
27+
"github.com/stretchr/testify/require"
28+
"go.uber.org/dig/internal/digreflect"
29+
)
30+
31+
func TestNewDotCtor(t *testing.T) {
32+
type t1 struct{}
33+
type t2 struct{}
34+
35+
n, err := newConstructorNode(func(A t1) t2 { return t2{} }, newScope(), constructorOptions{})
36+
require.NoError(t, err)
37+
38+
n.location = &digreflect.Func{
39+
Name: "function1",
40+
Package: "pkg1",
41+
File: "file1",
42+
Line: 24534,
43+
}
44+
45+
ctor := newDotCtor(n)
46+
assert.Equal(t, n.id, ctor.ID)
47+
assert.Equal(t, "function1", ctor.Name)
48+
assert.Equal(t, "pkg1", ctor.Package)
49+
assert.Equal(t, "file1", ctor.File)
50+
assert.Equal(t, 24534, ctor.Line)
51+
}
52+
53+
func TestNodeAlreadyCalled(t *testing.T) {
54+
type type1 struct{}
55+
f := func() type1 { return type1{} }
56+
57+
n, err := newConstructorNode(f, newScope(), constructorOptions{})
58+
require.NoError(t, err, "failed to build node")
59+
require.False(t, n.called, "node must not have been called")
60+
61+
c := New()
62+
require.NoError(t, n.Call(c.scope), "invoke failed")
63+
require.True(t, n.called, "node must be called")
64+
require.NoError(t, n.Call(c.scope), "calling again should be okay")
65+
}

dig_go19_test.go

Lines changed: 0 additions & 120 deletions
This file was deleted.

utils_for_pre_go19_test.go renamed to dig_int_test.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,10 @@
1818
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1919
// THE SOFTWARE.
2020

21-
//go:build !go1.9
22-
// +build !go1.9
23-
2421
package dig
2522

26-
import "reflect"
23+
import "math/rand"
2724

28-
func anonymousField(t reflect.Type) reflect.StructField {
29-
return reflect.StructField{Anonymous: true, Type: t}
25+
func SetRand(r *rand.Rand) Option {
26+
return setRand(r)
3027
}

0 commit comments

Comments
 (0)