尝试比较Web服务响应和文件中的预期xml

时间:2012-01-25 10:21:04

标签: web-services testing powershell

我们最多使用Java开发,但我们希望使用ms集成测试(使用https://github.com/scottmuc/Pester)我们的Web服务。为此,我正在编写连接到Web服务的powershell脚本,并将响应与我从文件加载的xml进行比较。

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$instance = New-WebServiceProxy -Uri "https://localhost:7002/service?WSDL" -Namespace "myspace"
$instance.Credentials = new-object System.Net.NetworkCredential("user", "pass")
...
$reply = $instance.fetchInformation($inputA, $inputB)
[xml]$expected = Get-Content ("expected.xml")
...

但是,现在我有一个$ reply,其中包含来自myspace命名空间的对象和包含XMLNode的$ expected。我看到两种方法可以做到这一点(可能还有更多):

  1. 获取原始XML响应并进行比较。但是,我似乎无法找到如何做到这一点。
  2. 将$ expected XML序列化到myspace命名空间对象中。那可能吗?

2 个答案:

答案 0 :(得分:1)

您可以将Web服务返回的响应序列化为XML,并将其与expected.xml文件的内容作为字符串进行比较。

以下是一个例子:

$writer = New-Object System.IO.StringWriter
$serializer = New-Object System.Xml.Serialization.XmlSerializer($reply.GetType())
$serializer.Serialize($writer, $reply)

$replyAsXml = $writer.ToString()
$expectedReplyAsXml = Get-Content expected.xml

$replyAsXml -eq $expectedReplyAsXml

请注意,在此示例中,您需要确保expected.xml文件中包含的XML与XmlSerializer返回的XML在间距和缩进方面的匹配。为了避免这种情况,您可以在比较它们之前从两个字符串中删除所有额外字符(例如空格换行符)。

答案 1 :(得分:0)

我最终得到了一种完全不同的方法。这两个XML彼此完全不同,所以我创建了一个自定义比较器。这使我可以简单地编写自定义代码来忽略无趣的差异。

这会导致一些原始代码完成这项工作:

# Assume two arrays of equal length
Function Zip {
    Param($a1, $a2)

    $sum = New-Object object[] $a1.Count
    For ($i = 0; $i -lt $a1.Count; ++$i) {
        $sum[$i] = New-Object object[] 2
        $sum[$i][0] = $a1[$i]
        $sum[$i][1] = $a2[$i]
    }
    Return ,$sum
}


Function XmlChildNodes2List{
    param($nodes)
    $myArray = New-Object object[] 0
    For ($i = 0; $i -lt $nodes.Count; ++$i) {
        $node = $nodes.Item($i)
        If ($node -ne $null) {
            $myArray += $node
        }
    }
    Return ,$myArray
}

Function ShowContext{
    Param($ctx)
    " at " + $ctx
}

Function CompareNode{
    Param($o1, $o2, $ctx)

    Try {
    Switch ($o1.GetType().Name) {
        "XmlDocument" {
            CompareXml $o1.ChildNodes $o2.ChildNodes
        }
        "XmlChildNodes" {
            $olist1 = XmlChildNodes2List $o1 | Sort
            $olist2 = XmlChildNodes2List $o2 | Sort
            If ($olist1.Count -ne $olist2.Count) {
                $msg = "Unequal child node count " + ($olist1 -join ",") + " and " + ($olist2 -join ",") + (ShowContext $ctx)
                throw $msg
            } Else {
                $list = Zip $olist1 $olist2
                $value = $true
                foreach ($item in $list) {
                    if ($value -eq $true) {
                        $value = CompareXml $item[0] $item[1] $ctx
                    }
                }
                $value
            }
        }
        "XmlElement" {
            If ($o1.LocalName -eq $o2.LocalName) {
                If ($o1.LocalName -eq "uninterestingElement" -or $o1.LocalName -eq "uninterestingElement2") {
                    $true
                } Else {
                    CompareXML $o1.ChildNodes $o2.ChildNodes ($ctx + "/" + $o1.LocalName)
                }
            } Else {
                throw ("Element " + $o1.LocalName + " != " + $o2.LocalName + (ShowContext $ctx))
            }
        }
        "XmlDeclaration" {
            $true
        }
        "XmlText" {
            $result = $o1.InnerText.Replace("`r`n","`n")
            $expect = $o2.InnerText.Replace("`r`n","`n")
            # TODO: Hack to remove timezone from expected dates in format 2005-09-01+02:00, the webservice side of the
            # reply to xml-conversion looses them
            If ($expect -match "^(\d{4}-\d\d-\d\d)\+\d\d:\d\d$") {
                $expect = $Matches[1]
            }
            If ($result -eq $expect) {
                $true
            } Else {
                throw ($o1.InnerText + " is not equal to " + $o2.InnerText + (ShowContext $ctx))
            }
        }
        Default {
            throw ("What to do with node " + $o1.GetType().Name + (ShowContext $ctx))
        }
    }
    } Catch [Exception] {
        throw $_
    }
}

Function CompareXML{
    Param($o1, $o2, $ctx)

    If ($o1 -eq $null -and $o2 -eq $null) {
        $true
    } ElseIf ($o1 -eq $null -or $o2 -eq $null) {
        throw ("Response or expected is null")
    } ElseIf ($o1.GetType() -eq $o2.GetType()) {
        CompareNode $o1 $o2 $ctx
    } Else {
        throw ($o1.GetType().Name + " is not " + $o2.GetType().Name + (ShowContext $ctx))
    }
}

然后可以在两个XML上运行:

CompareXML $result $expected ""