0

我正在尝试测试一种发出两个连续 Web 请求的方法。

到目前为止,我只使用这个解决方案使用一个名为 TestWebRequest 的对象测试了单个请求,它就像单个请求的魅力一样。如果您不熟悉它,TestWebRequest 会拦截 Web 请求机制并在幕后工作以返回预期的响应。这使得在不使用模拟的情况下测试实际服务成为可能。

但是现在我的一种方法的逻辑已经变成了这样的东西(在伪代码中)

public void MakePayment(PaymentRequest request)
{
    var statusRequest = webService.GetPaymentStatus(new PaymentStatusRequest()
            {
                OrderId = request.OrderId
            });

    if (statusRequest.StatusId != 100)
    {
     var responseXml = webService.GetResponse(GetRequestXml(request));
     /*.. process response ..*/
    }
}

有没有办法扩展TestWebRequest来处理两个请求,或者有没有可以用来测试这个方法的替代方法?

这是一个工作测试的例子:

 [Test]
 public void MakePayment()
 {
      var response = @"<XML>..</XML>";
      TestWebRequest request = TestWebRequestCreate.CreateTestRequest(response);
      var result = webService.MakePayment(1, new PaymentRequest());
      var expectedResponse = new PaymentResponse()
      {
          Status = 23
      };
      Assert.AreEqual(expectedResponse, result);  
 }

现在,如果 MakePayment 突然发出两个请求,那么我们需要一种方法来模拟两个假响应,如下所示:

 [Test]
 public void MakePayment()
 {
      var response1 = @"<XML>..</XML>";
      var response2 =  @"<XML>..</XML>";
      TestWebRequest request1 = TestWebRequestCreate.CreateTestRequest(response1);
      TestWebRequest request2= TestWebRequestCreate.CreateTestRequest(response2);
      var result = webService.MakePayment(1, new PaymentRequest());
      var expectedResponse = new PaymentResponse()
      {
          Status = 23
      };
      Assert.AreEqual(expectedResponse, result);  
 }

这是行不通的。

提前致谢

4

2 回答 2

0

您是否测试了您作为工作测试提供的示例?这不会通过,因为expectedResponse在您的测试代码中实例化并且不能与从webService.MakePayment调用返回的对象相同。您链接到的文章是测试 2 个字符串是否相等,而不是 2 个复杂类型。您实际上也没有使用TestWebRequest您在测试中实例化的对象。

webRequest.MakePayment也就是说,您可以通过控制创建并传递给 2 个调用的 2 个请求或使用 Moq 的回调功能来完成您要测试的内容,如下所示(未经测试的代码):

webRequestMock.Setup(x => x.MakePayment(1, It.IsAny<PaymentRequest>()).Returns(It.IsAny<PaymentResponse>()).CallBack((PaymentRequest request, PaymentResponse response) => VerifyResponse(request, response));

private void VerifyResponse(PaymentRequest request, PaymentResponse response) 
{
    // do some checks to determine whether it's the first call or the second, based on something uniquely different between to 2 requests - I need more actual code from you before I can tidy this up
    // e.g. (pseudocode)
    if (request.SomeValue == firstRequestValue) 
    {
        response.ShouldEqual(firstReponse);
    }
    else 
    {
        response.ShouldEqual(secondReponse);
    }

}

我说这是未经测试的代码,因为我不确定是否可以捕获返回的响应并将其传递给回调(因为它是返回值)。

于 2013-06-21T12:22:38.997 回答
0

我通过更新 TestWebReqestCreate 工厂方法来接受两个请求来让它工作。

这是更新的代码。它不是很优雅,但适用于两个请求,您不必为单个请求更改所有现有测试。

我想它可以更新为链接任意数量的请求,但我现在不需要这样做,所以我想出了一些快速的东西。

我希望这可以帮助像我一样被困的人

internal class TestWebRequestCreate : IWebRequestCreate
    {
        static WebRequest nextRequest;
        static WebRequest nextRequest2;
        private static bool used = false;
        static object lockObject = new object();

        static public WebRequest NextRequest
        {
            get { return nextRequest; }
            set
            {
                lock (lockObject)
                {
                    nextRequest = value;
                }
            }
        }

        /// <summary>See <see cref="IWebRequestCreate.Create"/>.</summary>
        public WebRequest Create(Uri uri)
        {
            if (used)
            {
                return nextRequest2;
            }
            else
            {
                used = true;
                return nextRequest;
            }
        }

        /// <summary>Utility method for creating a TestWebRequest and setting
        /// it to be the next WebRequest to use. It can now accept a subsequent request</summary>
        /// <param name="response1">The response the TestWebRequest will return.</param>
        /// <param name="response2">The subsequent response the TestWebRequest will return.</param>
        public static TestWebRequest CreateTestRequest(string response1, string response2 = null)
        {
            TestWebRequest request1 = new TestWebRequest(response1);
            used = false;
            nextRequest = request1;

            if (!string.IsNullOrEmpty(response2))
            {
                TestWebRequest request2 = new TestWebRequest(response2);
                nextRequest2 = request2;
            }

            return request1;
        }
    }
于 2013-06-26T17:16:51.447 回答