/
config_mock.go
97 lines (87 loc) · 2.34 KB
/
config_mock.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Copyright The ActForGood Authors.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://github.com/actforgood/xconf/blob/main/LICENSE.
package xconf
import (
"sync"
"sync/atomic"
)
// MockConfig is a mock for xconf.Config contract, to be used in UT.
type MockConfig struct {
cfg *DefaultConfig
getCallsCnt uint32
getCallback func(key string, def ...any)
configMap map[string]any
mu *sync.Mutex
}
// NewMockConfig instantiates new mocked Config with given key-values configuration.
// Make sure you pass an even number of elements and that the keys are strings.
//
// Usage example:
//
// mock := xconf.NewMockConfig(
// "foo", "bar",
// "year", 2022,
// )
func NewMockConfig(kv ...any) *MockConfig {
mock := &MockConfig{
configMap: make(map[string]any),
mu: new(sync.Mutex),
}
mock.SetKeyValues(kv...)
return mock
}
// Get mock logic.
func (mock *MockConfig) Get(key string, def ...any) any {
atomic.AddUint32(&mock.getCallsCnt, 1)
if mock.getCallback != nil {
mock.getCallback(key, def...)
}
return mock.cfg.Get(key, def...)
}
// SetKeyValues sets/resets given key-values.
// Make sure you pass an even number of elements and that the keys are strings.
func (mock *MockConfig) SetKeyValues(kv ...any) {
kvLen := len(kv)
if len(kv)%2 == 1 {
kvLen-- // skip last element
}
mock.mu.Lock()
for i := 0; i < kvLen; i += 2 {
key, ok := kv[i].(string)
if !ok {
continue
}
value := kv[i+1]
mock.configMap[key] = value
}
defCfg, _ := NewDefaultConfig(PlainLoader(mock.configMap))
_ = defCfg.Close()
mock.cfg = defCfg
mock.mu.Unlock()
}
// SetGetCallback sets the given callback to be executed inside Get() method.
// You can inject yourself to make assertions upon passed parameter(s) this way.
//
// Usage example:
//
// mock.SetGetCallback(func(key string, def ...any) {
// switch mock.GetCallsCount() {
// case 1:
// if key != "expectedKeyAtCall1" {
// t.Error("...")
// }
// case 2:
// if key != "expectedKeyAtCall2" {
// t.Error("...")
// }
// }
// })
func (mock *MockConfig) SetGetCallback(callback func(key string, def ...any)) {
mock.getCallback = callback
}
// GetCallsCount returns the no. of times Get() method was called.
func (mock *MockConfig) GetCallsCount() int {
return int(atomic.LoadUint32(&mock.getCallsCnt))
}