Skip to content

Using RegisterAlias together with ReadConfig does not work? #560

@brocaar

Description

@brocaar

Context

During an update of my application I made a change to my configuration format and was hoping by using RegisterAlias, to deal with this change in a backwards compatible way. I'm not sure if the failing testcase below is expected behavior or not.

From the README example:

viper.RegisterAlias("loud", "Verbose")

viper.Set("verbose", true) // same result as next line
viper.Set("loud", true)   // same result as prior line

viper.GetBool("loud") // true
viper.GetBool("verbose") // true

As the example sets the value using two keys, my assumption is that ReadConfig would do the same as it is just an other way to set config variables.

Testcase

In my case, I wanted to refactor loud to verbose. I expect that by using an alias, I would be able to handle this change. However, depending if I'm using RegisterAlias(A, B) or RegisterAlias(B, A), either the "old" or "new" configuration file isn't parsed correctly:

import (
	"bytes"
	"testing"

	"github.com/spf13/viper"
)

type UnmarshalWithAliasConfig struct {
	Verbose bool `mapstructure:"verbose"`
}

func TestReadConfigWithAlias(t *testing.T) {
	tests := []struct {
		ConfigFile    string
		ExpectedValue bool
	}{
		{ // 0
			ConfigFile: `
			loud=true
			`,
			ExpectedValue: true,
		},
		{ // 1
			ConfigFile: `
			verbose=true
			`,
			ExpectedValue: true,
		},
	}

	for i, test := range tests {
		v := viper.New()

		// test 0 fails and test 1 passes
		v.RegisterAlias("loud", "verbose")

		// test 0 passes and test 1 fails
		// v.RegisterAlias("verbose", "loud")

		v.SetConfigType("toml")
		if err := v.ReadConfig(bytes.NewBuffer([]byte(test.ConfigFile))); err != nil {
			t.Fatal(err)
		}

		// instead of ReadConfig using Set makes the tests pass, it works
		// with either key name:
		// v.Set("verbose", true)
		// v.Set("loud", true)

		if v := v.GetBool("verbose"); v != test.ExpectedValue {
			t.Errorf("[%d] expected from GetBool: %t, got: %t", i, test.ExpectedValue, v)
		}

		var c UnmarshalWithAliasConfig
		if err := v.Unmarshal(&c); err != nil {
			t.Fatal(err)
		}

		if c.Verbose != test.ExpectedValue {
			t.Errorf("[%d] expected in struct: %t, got: %t", i, test.ExpectedValue, c.Verbose)
		}
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions