2

Short description:

I'm trying use Pester to mock the contents of a file and then iterate through each line and each character of that fake data, but I'm getting this error: "the array index evaluated to null." when trying to access the characters of a line.

Background:

I have a Powershell function that reads the contents of the global.asax.cs file.

Example of the file I'm reading from:

namespace MockData
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        { 
            MvcHandler.DisableMvcResponseHeader = true;
        }
    }
}

Then, my function will use Get-Content to read the file and iterate through each line and each character. Example (simplified version, the $index variable looks nasty in this example but it's needed in the real code):

        $contents = Get-Content $filePath
        $index = 0
        $bracketCounter = 0

        Do {
            foreach($char in  $contents[$index].ToCharArray()) {
                if($char -eq "{") {
                    $bracketCounter++
                }
                elseif ($char -eq "}") {
                    $bracketCounter--
                }
            }
            $index++
        } While ($bracketCounter -gt 0)

Now in Pester, this is the code for my test:

It "check for success" {
    Mock Get-Content {
        $content = "namespace MockData
        {
            public class WebApiApplication : System.Web.HttpApplication
            {
                protected void Application_Start()
                { 
                    MvcHandler.DisableMvcResponseHeader = true;
                }
            }
        }"
        return $content
    } -ParameterFilter { $Path -like "*asax*"}

    [string[]]$errors = MyPowershellFile
    $errors | should BeNullOrEmpty
}

Expected results:

My expected results is that the Pester test iterates through the mock contents the same way it does with the real contents.

The error from Pester happens when calling this line:

foreach($char in  $contents[$index].ToCharArray()) 

I get "RuntimeException: Index operation failed; the array index evaluated to null."

I think this happens because in the real function, the first element of $contents is the first line of the file.

$contents[0] = namespace MockData

While in the Pester function, the first element of $contents is the first character.

$contents[0] = n

Is there a good way to work around this? I'm running out of ideas.

Thanks in advance for anyone reading this question.

Emiliano Rodriguez
  • 454
  • 2
  • 6
  • 19

2 Answers2

4

Why not write to the TestDrive and then mock:

Describe 'test things' {
#create a here-string and write the contents to the testdrive
@"
    namespace MockData
    {
        public class WebApiApplication : System.Web.HttpApplication
        {
            protected void Application_Start()
            { 
                MvcHandler.DisableMvcResponseHeader = true;
            }
        }
    }
"@ | Set-Content -Path TestDrive:\testfile.txt

    #Set up the mock to get-content
    Mock Get-Content {
        Get-Content TestDrive:\testfile.txt
    } -ParameterFilter {$path -like "*asax*"}

    #make sure the content matches
    it "finds strings in mocked content" {
        Get-Content abc.asax | Select-String MVCHandler | Should -Match 'MvcHandler.DisableMvcResponseHeader = true;'
    }

    #make sure the line count is correct
    it 'should have 10 lines of content' {
        (Get-Content def.asax).Count | Should -BeExactly 10
    }

    #make sure our mock was called the correct number of times
    it "called mocked get-content twice" {
        Assert-MockCalled Get-Content -Times 2
    }
}

This will create an actual file that mimics production so that you can test it correctly.

StephenP
  • 3,895
  • 18
  • 18
1

Get-Content returns an array of string, while your mock returns a single string.

Try following code:

It "check for success" {
Mock Get-Content {
    $content = @("namespace MockData"
    "{"
    "    public class WebApiApplication : System.Web.HttpApplication"
    "    {"
    "        protected void Application_Start()"
    "        { "
    "            MvcHandler.DisableMvcResponseHeader = true;"
    "        }"
    "    }"
    "}")
    return $content
} -ParameterFilter { $Path -like "*asax*"}

[string[]]$errors = MyPowershellFile
$errors | should BeNullOrEmpty
}
Moerwald
  • 10,448
  • 9
  • 43
  • 83
  • This makes things better but there is another issue. In the real code i'm searching for a specific line in the .cs file . $foundLine = $contents | Select-String -Pattern $lineToSearch Select-String doesn't work with this array of strings. – Emiliano Rodriguez May 06 '19 at 19:40
  • What does `$lineToSearch` looks like? – Moerwald May 07 '19 at 07:03
  • looks like this $lineToSearch = "MvcHandler.DisableMvcResponseHeader = true;". StephenP solved my issue though. Thanks a lot Moerwald! – Emiliano Rodriguez May 07 '19 at 14:13