Как Пестер может издеваться над функцией «test» в шаблоне «существование теста (не найдено) - создать - снова проверить, чтобы подтвердить создание»? - PullRequest
4 голосов
/ 30 июня 2019

Вот некоторый псевдокод, показывающий функцию для проверки:

function Set-Something
{
    if (Test-Something)
    {
        return $True
    }

    # Not found so do something to create it.
    Do-Something

    # Check it's been created successfully.
    if (Test-Something)
    {
        return $True
    }

    return $False
}

Это должен быть довольно распространенный шаблон: «Тест на существование - если не найден, создать - протестировать снова, чтобы проверить создание». Тестирование большинства веток довольно простое, но как я могу проверить ветку, в которой Test-Something терпит неудачу при первом вызове, а затем успешно при втором вызове?

Это мой тестовый код:

Describe 'Set-Something' {

    Context 'already exists' {
        Mock Test-Something { return $True }
        Mock Do-Something

        It 'returns True' {
            { Set-Something } | Should -Be $True
        }

        It 'does not call Do-Something' {
            Set-Something
            Assert-MockCalled Do-Something -Times 0 -Exactly
        }
    }

    Context 'does not already exist and creation fails' {
        Mock Test-Something { return $False }
        Mock Do-Something

        It 'calls Do-Something' {
            Set-Something
            Assert-MockCalled Do-Something -Times 1 -Exactly
        }

        It 'calls Test-Something twice' {
            Set-Something
            Assert-MockCalled Test-Something -Times 2 -Exactly
        }

        It 'returns False' {
            { Set-Something } | Should -Be $False
        }
    }

    Context 'does not already exist and creation succeeds' {
        Mock Test-Something { ?? }
        Mock Do-Something

        It 'calls Do-Something' {
            Set-Something
            Assert-MockCalled Do-Something -Times 1 -Exactly
        }

        It 'calls Test-Something twice' {
            Set-Something
            Assert-MockCalled Test-Something -Times 2 -Exactly
        }

        It 'returns True' {
            { Set-Something } | Should -Be $True
        }
    }
}

Проблема "еще не существует, и создание успешно завершено" - это проблема. Test-Something необходимо смоделировать, чтобы он проваливался при первом вызове, и успешно во второй раз. Аргументы, передаваемые Test-Something, будут идентичны при каждом вызове, поэтому я не могу использовать ParameterFilter для создания двух макетов Test-Something с другим поведением.

1 Ответ

1 голос
/ 04 июля 2019

Я нашел несколько способов посмеяться над этим:

1) Используйте «статическую» (т. Е. Ограниченную сценарием) переменную для записи состояния

Context 'does not already exist and creation succeeds' {

    BeforeEach {
        $script:exists = $False
    }

    AfterAll {
        Remove-Variable exists -Scope Script
    }

    Mock Test-Something { 
        return $script:exists
    }

    Mock Do-Something {
        $script:exists = $True
    }

    It 'calls Do-Something' {
        Set-Something
        Assert-MockCalled Do-Something -Times 1 -Exactly
    }

    It 'calls Test-Something twice' {
        Set-Something
        Assert-MockCalled Test-Something -Times 2 -Exactly
    }

    It 'returns True' {
        { Set-Something } | Should -Be $True
    }
}

2) Использовать хеш-таблицу для записи состояния

Context 'does not already exist and creation succeeds' {

    BeforeEach {
        $mockState = @{
                        ItExists = $False    
                    }
    }

    Mock Test-Something { 
        return $mockState.ItExists
    }

    Mock Do-Something {
        $mockState.ItExists = $True
    }

    It 'calls Do-Something' {
        Set-Something
        Assert-MockCalled Do-Something -Times 1 -Exactly
    }

    It 'calls Test-Something twice' {
        Set-Something
        Assert-MockCalled Test-Something -Times 2 -Exactly
    }

    It 'returns True' {
        { Set-Something } | Should -Be $True
    }
}   

Лично мне нравится хеш-таблица, потому что мне кажется, что $mockState. ... лучше указывает назначение переменной, чем $script:.... Кроме того, переменная в сценарии может вызвать состояние гонки, если тесты когда-либо были распараллелены, а другой блок Describe изменил эту же переменную.

...