1// Copyright 2018 The Wire Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// This test demonstrates how to use mocks with wire. 16 17package main 18 19import ( 20 "fmt" 21 "time" 22 23 "github.com/google/wire" 24) 25 26func main() { 27 // Create a "real" greeter. 28 // Greet() will include the real current time, so elide it for repeatable 29 // tests. 30 fmt.Printf("Real time greeting: %s [current time elided]\n", initApp().Greet()[0:15]) 31 32 // There are two approaches for creating an app with mocks. 33 34 // Approach A: create the mocks manually, and pass them to an injector. 35 // This approach is useful if you need to prime the mocks beforehand. 36 fmt.Println("Approach A") 37 mt := newMockTimer() 38 mockedApp := initMockedAppFromArgs(mt) 39 fmt.Println(mockedApp.Greet()) // prints greeting with time = zero time 40 mt.T = mt.T.AddDate(1999, 0, 0) 41 fmt.Println(mockedApp.Greet()) // prints greeting with time = year 2000 42 43 // Approach B: allow the injector to create the mocks, and return a struct 44 // that includes the resulting app plus the mocks. 45 fmt.Println("Approach B") 46 appWithMocks := initMockedApp() 47 fmt.Println(appWithMocks.app.Greet()) // prints greeting with time = zero time 48 appWithMocks.mt.T = appWithMocks.mt.T.AddDate(999, 0, 0) 49 fmt.Println(appWithMocks.app.Greet()) // prints greeting with time = year 1000 50} 51 52// appSet is a provider set for creating a real app. 53var appSet = wire.NewSet( 54 wire.Struct(new(app), "*"), 55 wire.Struct(new(greeter), "*"), 56 wire.InterfaceValue(new(timer), realTime{}), 57) 58 59// appSetWithoutMocks is a provider set for creating an app with mocked 60// dependencies. The mocked dependencies are omitted and must be provided as 61// arguments to the injector. 62// It is used for Approach A. 63var appSetWithoutMocks = wire.NewSet( 64 wire.Struct(new(app), "*"), 65 wire.Struct(new(greeter), "*"), 66) 67 68// mockAppSet is a provider set for creating a mocked app, including the mocked 69// dependencies. 70// It is used for Approach B. 71var mockAppSet = wire.NewSet( 72 wire.Struct(new(app), "*"), 73 wire.Struct(new(greeter), "*"), 74 wire.Struct(new(appWithMocks), "*"), 75 // For each mocked dependency, add a provider and use wire.Bind to bind 76 // the concrete type to the relevant interface. 77 newMockTimer, 78 wire.Bind(new(timer), new(*mockTimer)), 79) 80 81type timer interface { 82 Now() time.Time 83} 84 85// realTime implements timer with the real time. 86type realTime struct{} 87 88func (realTime) Now() time.Time { return time.Now() } 89 90// mockTimer implements timer using a mocked time. 91type mockTimer struct { 92 T time.Time 93} 94 95func newMockTimer() *mockTimer { return &mockTimer{} } 96func (m *mockTimer) Now() time.Time { return m.T } 97 98// greeter issues greetings with the time provided by T. 99type greeter struct { 100 T timer 101} 102 103func (g greeter) Greet() string { 104 return fmt.Sprintf("Good day! It is %v", g.T.Now()) 105} 106 107type app struct { 108 g greeter 109} 110 111func (a app) Greet() string { 112 return a.g.Greet() 113} 114 115// appWithMocks is used for Approach B, to return the app plus its mocked 116// dependencies. 117type appWithMocks struct { 118 app app 119 mt *mockTimer 120} 121