Pester如何模拟“测试存在(未找到)-创建-再次测试以确认创建”模式中的“测试”功能?

时间:2019-06-30 00:36:22

标签: powershell unit-testing pester

下面是一些伪代码,显示了要测试的功能:

/* eslint-disable no-console */
import React, { Component } from 'react';
import { DatePicker } from 'native-base';
import { Row, Col } from 'react-native-easy-grid';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      meetingDate: null,
      // eslint-disable-next-line react/no-unused-state
      data: {},
    };
  }

  static getDerivedStateFromProps = (props, state) => {
    if (props.data !== state.data) {
      const {
        meetingDate,
      } = props.data;

      return {
        meetingDate: meetingDate ? new Date(meetingDate.getFullYear(), meetingDate.getMonth(), meetingDate.getDate()) : null,
      };
    }
    return null;
  }

  onMeetingDate = (meetingDate) => {
    this.setState({ meetingDate });
  }

  render() {
    console.log('meetDate render: ', this.state.meetingDate);
    /**
     * If the meetingDate from props has value, this will print the date from props
     * if I declare the meetingDate state at constructor with new Date(20, 1, 2019), this will make the default date show what I want
     * But, if I set it null, even in this console print the right value, the default date wont change.
     */
    return (
      <React.Fragment>
        <Row>
          <Col>
            <DatePicker
              defaultDate={
                this.state.meetingDate
              }
              animationType="fade"
              androidMode="spinner"
              onDateChange={this.onMeetingDate}
            />
          </Col>
        </Row>
      </React.Fragment>
    );
  }
}

export default App;

这必须是一个相当普遍的模式:“测试存在-如果找不到,请创建-再次测试以验证创建”。测试大多数分支非常简单,但是如何在第一次调用Test-Something失败然后第二次调用成功的地方测试分支?

这是我到目前为止的测试代码:

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进行模拟,以便它在第一次调用时失败,而在第二次调用时成功。每次调用传递给Test-Something的参数都将是相同的,因此我不能使用ParameterFilter来创建两个具有不同行为的Test-Something模拟。

1 个答案:

答案 0 :(得分:1)

我发现了两种模拟方法:

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块修改了相同的变量,则脚本作用域的变量可能会导致竞争。