私は、基本的には様々なパスワードストア(Ansible Vault、Hashicorp Vault、Chef Vaultなど)のラッパーである小さなGoアプリケーションに取り組んでいます。アイデアは:私のさまざまなプロビジョニングスクリプトでは、Goラッパーを使って秘密を掴むことができます。パスワードストアをバックグラウンドで切り替えると、すべてのインターフェイスをプロジェクト全体で更新する必要はありません。依存性注入とテスト
私はこのアプリケーションの適切なテストをセットアップしようとしています。そうすることで、依存関係を挿入する最良の方法を見つけようとしています。
たとえば、プロジェクトの名前がsecrets
であるとします。私の実装の1つはansible
です。また、実行可能な実装では、独自のparser
が必要であり、データを取得するために、自身のconnection
を安全な格納域に開かなければなりません。
だから私は、次のものがあります:
package secrets
type PasswordStore interface {
GetKey(key string) (string, error)
}
func New(backend string, config map[string]interface{}) (PasswordStore, error) {
switch backend {
case "ansible":
return ansible.New(config)
default:
return nil, fmt.Errorf("Password store '%s' not supported.", backend)
}
}
package ansible
type Connection interface {
open() (string, error)
}
type Ansible struct {
connection Connection
contents map[string]string
}
func New(c map[string]interface{}) (*Ansible, error) {
conn, err := NewConnection(c["ansible_path"].(string))
if err != nil {
return nil, err
}
// open connection, parse, etc...
a := &Ansible{
connection: conn,
contents: parsedData,
}
return a, nil
}
secrets
パッケージがいくつかとansible
パッケージの依存関係(接続)の知識、および工場インスタンスまでちょうど新しいのを必要としないので、これは良い方法だと思われ設定データ。しかし、私はAnsibleが受け取るconnection
を模擬する必要がある場合(つまり設定マップはmock
と呼ばれる接続オプションを持っていない限り)、これを行うには良い方法があるようには思えない
他のオプションは、工場を放棄することです、と同じように、secrets
パッケージからすべての依存関係を組み立てる:
package secrets
type PasswordStore interface {
GetKey(key string) (string, error)
}
func New(backend string, config map[string]interface{}) (PasswordStore, error) {
switch backend {
case "ansible":
return ansible.New(AnsibleConnection{}, config)
default:
return nil, fmt.Errorf("Password store '%s' not supported.", backend)
}
}
package ansible
// same as before in this file, but with injected dependency ...
func New(connect Connection, c map[string]interface{}) (*Ansible, error) {
conn, err := connect.NewConnection(c["ansible_path"].(string))
if err != nil {
return nil, err
}
// open connection, parse, etc...
a := &Ansible{
connection: conn,
contents: parsedData,
}
return a, nil
}
今依存性が注入されたが、すべての実装のために、すべての依存関係の知識を持っているsecrets
ニーズのように思えるされます。
secrets
がそれほど知っていないようにこれを構造化するより論理的な方法がありますか?あるいは、トップレベルのパッケージがすべてを編成するのは典型的なことですか?
ご返信ありがとうございます。はい、私は不可能な設定マップを持っています。新しい()メソッドはすべての設定データを持っています(おそらくファイルか何かから引っ張られたもの)。私の質問は、あなたが 'store'に何かを模倣したいのであれば、モックを提供する設定キーがありますか? – djt
いいえ、私は完全にファクトリ関数をスキップし、テスト中のユニットに直接スタブ/モックを渡します。 – Adrian