lundi 28 janvier 2019

Mocking bufio.Scanner input

I've had a lot of success defining interfaces and substituting mocks during testing, but I've hit a problem with mocking bufio.Scanner input:

file := &mockFile{
    ReadFunc: func(p []byte) (int, error) {
        reader := bufio.NewReader(bytes.NewReader([]byte(consulPropertiesFile)))
        return reader.Read(p)
    },
    CloseFunc: func() error {
        return nil
    },
}

fs := &mockFileSystem{
    OpenFunc: func(name string) (File, error) {
        return file, nil
    },
}

properties, err := readConsulPropertiesFile(fs)

While this seems to work, once the scanner has gotten to the end of my string, it just seems to return to the beginning, and reads too much (it seems to read more than a line this time around). It's like I need to manually return an EOF error at the appropriate time in my ReadFunc, but I'm not sure how to figure out when I should do that...

Scanner code (lifted from here):

f, err := file.Open("/run/secrets/consul-web4.properties")
if err != nil {
    return nil, err
}
defer f.Close()

properties := map[string]string{}

scanner := bufio.NewScanner(f)
for scanner.Scan() {
    line := scanner.Text()
    if equal := strings.Index(line, "="); equal >= 0 {
        if key := strings.TrimSpace(line[:equal]); len(key) > 0 {
            value := ""
            if len(line) > equal {
                value = strings.TrimSpace(line[equal+1:])
            }
            properties[key] = value
        }
    }
}

I've yet to refactor the above...

I've tried the following variations on my test string:

const input = `key=value
key=value
key=value
`

const input = "key=value\nkey=value\nkey=value\n"

And I've tried bufio.Reader & io.Reader implementations.

Any help / insight appreciated!

Aucun commentaire:

Enregistrer un commentaire