การทดสอบหน่วย ASP.NET WebApi ด้วย Request.CreateResponse


147

ฉันกำลังพยายามเขียนการทดสอบหน่วยสำหรับ ApiController ของฉันและประสบปัญหาบางอย่าง มีวิธีการขยายที่ดีที่เรียกว่า Request.CreateResponse ที่ช่วยได้มากในการสร้างการตอบสนอง

public HttpResponseMessage Post(Product product)
{
  var createdProduct = repo.Add(product);
  return this.Request.CreateResponse(HttpStatusCode.Created, createdProduct);
}

มีวิธีใดในการเยาะเย้ย CreateResponse โดยไม่ใช้ mocks บางส่วนหรือใช้โดยตรงของ "HttpResponseMessage ใหม่ (... )"


1
ทำไมคุณต้องการที่จะเยาะเย้ยCreateResponse? ทำไมไม่ยืนยันในคืนHttpResponseMessage ContentและStatusCodeคุณสมบัติที่ตั้งค่าที่ถูกต้อง?
nemesv

3
ถ้าฉันเรียกใช้การทดสอบแบบหน่วยวิธีนี้มันจะล้มเหลวโดยมีข้อยกเว้นว่าการกำหนดค่าไม่ได้ตั้งค่าไว้
asa

1
ตกลงอัปยศฉันฉันแค่ต้องเขียนนี้ขอให้สร้าง Reesponse (HttpStatusCode.Acepted, createdProduct, GlobalConfiguration.Configuration)
asa

คำตอบ:


243

อีกวิธีในการแก้ไขปัญหานี้คือทำดังต่อไปนี้:

controller.Request = new HttpRequestMessage();
controller.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, 
                                  new HttpConfiguration());

หากคุณกำลังอัปเกรดเป็น webapi 5.0 คุณจะต้องเปลี่ยนเป็น:

controller.Request = new HttpRequestMessage();
controller.Request.SetConfiguration(new HttpConfiguration());

เหตุผลที่คุณต้องทำเช่นนี้ก็เพราะคุณจะต้องมีRequestประชากรในตัวควบคุมมิฉะนั้นวิธีการขยายบนRequestจะไม่ทำงาน คุณต้องHttpConfigurationตั้งค่าในคำขอมิฉะนั้นการกำหนดเส้นทางและส่วนอื่น ๆ ของไปป์ไลน์จะทำงานไม่ถูกต้อง


ใช่มันอาจใช้งานได้เช่นกัน แต่ดูเหมือนว่า Request.CreateResponse ก็ใช้ได้เช่นกัน
asa

4
การเพิ่ม GlobalConfiguration.Configuration ยังคงเป็นคำขอว่าง การตั้งค่าคำขอใช้งานได้สำหรับฉัน แต่นี่ไม่ใช่จุดสิ้นสุดของปัญหาของฉันเนื่องจากการกระทำของฉันเรียก Url.Link และชื่อเส้นทางไม่ได้ถูกกำหนดไว้
foolshat

ช่วยในการตั้งค่าเส้นทางstackoverflow.com/questions/11779311/…
foolshat

การตั้งค่า ControllerContext หลังจากการโทรนี้จะให้ข้อผิดพลาดนั้นด้วย แต่เฉพาะกับ WebApi 5.0.0 แต่ถ้าฉันตั้งค่าวัตถุ HttpConfiguration ในการร้องขอล่าสุดมันก็ใช้ได้ดี
mikebridge

มันใช้งานได้ดี แต่ฉันไม่เข้าใจว่าทำไมมันถึงใช้ได้ คุณช่วยอธิบายเรื่องนี้ในคำตอบได้ไหม?
Jan_V

24

คุณสามารถตั้งค่าวัตถุคอนโทรลเลอร์เพื่อทดสอบได้ดังนี้:

var config = new HttpConfiguration();
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/products");
var route = config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");
var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "products" } });

controller.ControllerContext = new HttpControllerContext(config, routeData, request);
controller.Request = request;
controller.Request.Properties[HttpPropertyKeys.HttpConfigurationKey] = config;

คัดลอกมาจากบล็อกโพสต์ปีเตอร์พระครูที่ครอบคลุมเกี่ยวกับหน่วยทดสอบเว็บ ASP.NET API


1
คุณอาจสนใจเอกสาร MS ที่เกี่ยวข้องกับเรื่องนี้: docs.microsoft.com/en-us/aspnet/web-api/overview/ ...... คุณอาจต้องเพิ่มการอ้างอิงไปยัง System.Web.Http และ System.Net Http
Aaron Hoffman

4

สำหรับ Web API 2 คุณสามารถเพิ่มได้

controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();

ชอบมาก ๆ

[TestMethod]
public void GetReturnsProduct()
{
    // Arrange
    var controller = new ProductsController(repository);
    controller.Request = new HttpRequestMessage();
    controller.Configuration = new HttpConfiguration();

    // Act
    var response = controller.Get(10);

    // Assert
    Product product;
    Assert.IsTrue(response.TryGetContentValue<Product>(out product));
    Assert.AreEqual(10, product.Id);
}

การตั้งค่าคำขอและการกำหนดค่าบนคอนโทรลเลอร์เป็นสิ่งสำคัญ มิฉะนั้นการทดสอบจะล้มเหลวด้วย ArgumentNullException หรือ InvalidOperationException

ดูที่นี่สำหรับข้อมูลเพิ่มเติม


1

WebAPI 1 ที่นี่มีปัญหาที่คล้ายกันโดยใช้ VB

ฉันจัดการกับการตอบสนองแบบไฮบริดที่นี่เพื่อให้การทำงานง่ายเหมือนนี้

Dim request As HttpRequestMessage = New HttpRequestMessage()
Return request.CreateResponse(HttpStatusCode.BadRequest, myCustomClassObject, GlobalConfiguration.Configuration)

เพียงโพสต์ในกรณีที่ช่วยใคร


0

ในคลาสทดสอบของคุณสร้างอินสแตนซ์ของคลาสตัวควบคุม เช่นvar customerController= new CustomerController();

customerController.Request = new HttpRequestMessage();
customerController.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.