我正在尝试测试一个连续发出两次Web请求的方法。
到目前为止,我只使用this solution using an object called 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);
}
哪个不起作用。
提前致谢
答案 0 :(得分: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);
}
}
我说这是未经测试的代码,因为我不确定是否可以捕获返回的响应并将其传递给回调(因为它是返回值)。
答案 1 :(得分: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;
}
}