如何用微软测试工具单元测试SOAP请求XML处理方法并模拟请求
问题描述
需要测试一个从SOAP Body中提取并格式化请求XML的静态方法GetSoapXmlRequest,该方法依赖HttpContext.Current.Request.InputStream获取SOAP请求,当前编写的测试未正确模拟请求内容,无法验证方法逻辑。
待测试方法代码:
public static string GetSoapXmlRequest() { XmlDocument xmlSoapRequest = new XmlDocument(); string strFormatedXML = string.Empty; try { Logger.Info("-----------Starting of GetSoapXmlRequest method Call-------"); Logger.Info(MethodBase.GetCurrentMethod().ToString()); using (Stream receiveStream = HttpContext.Current.Request.InputStream) { if (receiveStream.Position > 0) { receiveStream.Position = 0; } using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8)) { xmlSoapRequest.Load(readStream); } } Logger.Info(AsString(xmlSoapRequest)); if (xmlSoapRequest.ChildNodes.Count > 0) { XDocument xmlInputSoapRequest = XDocument.Parse(xmlSoapRequest.OuterXml); XElement soapAuthToken = xmlInputSoapRequest.Root.Elements().FirstOrDefault(); XElement soapBody = xmlInputSoapRequest.Root.Elements().LastOrDefault(); XmlReader readerSoapAuthToken = soapAuthToken.CreateReader(); var xmlSoapAuthToken = XDocument.Load(readerSoapAuthToken); XmlReader readerSoapBody = soapBody.CreateReader(); var xmlSoapBody = XDocument.Load(readerSoapBody); xmlSoapAuthToken.Root.Add(xmlSoapBody.Root.Elements()); strFormatedXML = xmlSoapAuthToken.ToString(); } Logger.Info(strFormatedXML); Logger.Info("-----------End of GetSoapXmlRequest method Call-------"); return strFormatedXML; } catch (Exception) { return string.Empty; } }
用户尝试的测试方法:
[TestMethod] public void GetSoapXmlRequest_PostUCCValidationResult_ReturnsTrue() { var req = new HttpRequest("", "http://tempuri.org", ""); HttpContext.Current = new HttpContext(req, new HttpResponse(new StringWriter())); string soapRequest = Utility.GetSoapXmlRequest(); Assert.AreEqual(true, string.IsNullOrEmpty(soapRequest)); }
解决方案
完成单元测试的核心是模拟包含SOAP请求内容的HttpRequest.InputStream,并验证方法返回的格式化XML是否符合预期。
1. 构造测试用的SOAP请求XML
准备一个符合结构的SOAP示例,包含Envelope、Header(AuthToken节点)和Body:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <AuthToken xmlns="http://example.com/auth"> <Token>abc123</Token> </AuthToken> </soap:Header> <soap:Body> <UCCValidationResult xmlns="http://example.com/services"> <Result>Success</Result> <UCCCode>123456789</UCCCode> </UCCValidationResult> </soap:Body> </soap:Envelope>
2. 模拟HttpRequest的InputStream
将SOAP XML转换为字节流,写入HttpRequest的InputStream中,同时重置流的位置确保方法能正确读取。
3. 完善测试方法
修改测试代码,添加流模拟逻辑,并断言返回结果是否符合预期(即AuthToken节点包含Body中的子元素):
[TestMethod] public void GetSoapXmlRequest_ValidSoapRequest_ReturnsFormattedXml() { // 1. 构造测试用的SOAP XML字符串 string soapXml = @"<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""> <soap:Header> <AuthToken xmlns=""http://example.com/auth""> <Token>abc123</Token> </AuthToken> </soap:Header> <soap:Body> <UCCValidationResult xmlns=""http://example.com/services""> <Result>Success</Result> <UCCCode>123456789</UCCCode> </UCCValidationResult> </soap:Body> </soap:Envelope>"; // 2. 将XML字符串转换为字节流 byte[] soapBytes = Encoding.UTF8.GetBytes(soapXml); MemoryStream inputStream = new MemoryStream(soapBytes); // 3. 创建模拟的HttpRequest并设置InputStream var req = new HttpRequest("", "http://tempuri.org", ""); req.InputStream = inputStream; // 重置流位置(避免方法读取时位置在末尾) inputStream.Position = 0; // 4. 设置HttpContext.Current HttpContext.Current = new HttpContext(req, new HttpResponse(new StringWriter())); // 5. 调用待测试方法 string result = Utility.GetSoapXmlRequest(); // 6. 断言结果:验证返回的XML包含AuthToken和Body中的子元素 Assert.IsFalse(string.IsNullOrEmpty(result)); Assert.IsTrue(result.Contains("<Token>abc123</Token>")); Assert.IsTrue(result.Contains("<Result>Success</Result>")); Assert.IsTrue(result.Contains("<UCCCode>123456789</UCCCode>")); }
额外优化建议
- 降低耦合度:原方法直接依赖静态的
HttpContext.Current,测试耦合度高。建议修改方法,将HttpRequest作为参数传入,比如:
测试时无需设置public static string GetSoapXmlRequest(HttpRequest request) { // 方法逻辑中使用传入的request,而非HttpContext.Current.Request }HttpContext.Current,直接传入模拟的HttpRequest即可,测试更简洁。 - 覆盖异常分支:补充测试用例,模拟读取流失败、XML格式错误等场景,验证方法是否返回空字符串。
内容的提问来源于stack exchange,提问作者LogicalDesk
相关产品推荐
相关产品推荐

