2012-04-06 12 views
18

¿Hay un código de muestra que muestre la unidad de prueba de un controlador que hereda del controlador api? Estoy intentando probar un POST por unidad, pero está fallando. Creo que necesito configurar el HttpControllerContext para probar pero no sé cómo GraciasCódigo de ejemplo para controladores de api de prueba unitaria

+0

¿Pregunta duplicada quizás? http://stackoverflow.com/questions/9483663/unit-testing-asp-net-web-api –

Respuesta

10

Este código debe demostrar los principios básicos de una prueba posterior. Asume que tienes un repositorio inyectado en el controlador. Estoy usando MVC 4 RC no Beta aquí si está usando la Beta Request.CreateResponse (... es un poco diferente así que dame un grito ...

código del controlador dado un poco como esto:

public class FooController : ApiController 
{ 
    private IRepository<Foo> _fooRepository; 

    public FooController(IRepository<Foo> fooRepository) 
    { 
     _fooRepository = fooRepository; 
    } 

    public HttpResponseMessage Post(Foo value) 
    { 
     HttpResponseMessage response; 

     Foo returnValue = _fooRepository.Save(value); 
     response = Request.CreateResponse<Foo>(HttpStatusCode.Created, returnValue, this.Configuration); 
     response.Headers.Location = "http://server.com/foos/1"; 

     return response; 
    } 
} 

La prueba de unidad se vería un poco como este (NUnit y RhinoMock)

 Foo dto = new Foo() { 
      Id = -1, 
      Name = "Hiya" 
     }; 

     IRepository<Foo> fooRepository = MockRepository.GenerateMock<IRepository<Foo>>(); 
     fooRepository.Stub(x => x.Save(dto)).Return(new Foo() { Id = 1, Name = "Hiya" }); 

     FooController controller = new FooController(fooRepository); 

     controller.Request = new HttpRequestMessage(HttpMethod.Post, "http://server.com/foos"); 
     //The line below was needed in WebApi RC as null config caused an issue after upgrade from Beta 
     controller.Configuration = new System.Web.Http.HttpConfiguration(new System.Web.Http.HttpRouteCollection()); 

     var result = controller.Post(dto); 

     Assert.AreEqual(HttpStatusCode.Created, result.StatusCode, "Expecting a 201 Message"); 

     var resultFoo = result.Content.ReadAsAsync<Foo>().Result; 
     Assert.IsNotNull(resultFoo, "Response was empty!"); 
     Assert.AreEqual(1, resultFoo.Id, "Foo id should be set"); 
+0

Tu publicación inadvertidamente descubrió un pequeño error en mi código. Había dejado el tercer parámetro para CreateResponse (..., this.Configuration). Tan pronto como lo agregué, mi Configuración nula para mi objeto de solicitud ya no era un problema. Espero que esto ayude a alguien más que está buscando – oddmeter

+0

Configuración de configuración por 'controller.Configuration = new System.Web.Http.HttpConfiguration (new System.Web.Http.HttpRouteCollection());' devuelto nulo en mi línea de respuesta de respuesta de acción, así que he intentado esto: controller.Request.Properties.Add (HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration()); Y funcionó. –

+0

-1 Esa es una cantidad horrible de código para poner en una prueba unitaria. [Hay mejores herramientas] (http://stackoverflow.com/a/22200520/11635) –

0

he creado solución general para llamar a algún tipo de acción y conseguir HttpResponseMessage como diccionario, que es muy conveniente para su uso.

Primera alguna extensión para el diccionario:

public static class DictionaryExtensions 
{ 
    public static void AddRange<T, S>(this Dictionary<T, S> source, 
             Dictionary<T, S> collection) 
    { 
     if (collection == null) 
     { 
      throw new NullReferenceException("Collection is null"); 
     } 

     foreach (var item in collection) 
     { 
      source.Add(item.Key, item.Value); 
     } 
    } 
} 

Ahora solicitar la creación de parte:

public class RequestCreator 
{ 
    protected static void FirstPart(ApiController controller, 
            HttpMethod method,String actionUrl) 
    { 
     // Creating basic request message with message type and requesting 
     // url example : 'http://www.someHostName/UrlPath/' 
     controller.Request = new HttpRequestMessage(method, actionUrl); 

     // Adding configuration for request 
     controller.Request.Properties. 
      Add(HttpPropertyKeys.HttpConfigurationKey,new HttpConfiguration());           
    } 

    protected static Dictionary<String, Object> SecondPart 
               (HttpResponseMessage response) 
    { 
     // Adding basic response content to dictionary 
     var resultCollection = new Dictionary<String, Object> 
     { 
      {"StatusCode",response.StatusCode}, 
      {"Headers",response.Headers}, 
      {"Version",response.Version}, 
      {"RequestMessage",response.RequestMessage}, 
      {"ReasonPhrase",response.ReasonPhrase}, 
      {"IsSuccessStatusCode",response.IsSuccessStatusCode} 
     }; 

     var responseContent = response.Content; 
     // If response has content then parsing it and 
     // getting content properties 
     if (null != responseContent) 
     { 
      var resultMessageString = response.Content. 
               ReadAsStringAsync().Result; 
      resultCollection.AddRange((new JavaScriptSerializer()). 
             DeserializeObject(resultMessageString) 
               as Dictionary<String, Object>); 
     } 


     return resultCollection; 
    }  
} 

Y, por último mensaje de respuesta al diccionario clase convertidor:

public class HttpResponseModelGetter : RequestCreator 
{ 
    public Dictionary<String, Object> 
       GetActionResponse(ApiController controller,HttpMethod method, 
          String actionUrl,Func<HttpResponseMessage> callBack) 
    { 
     FirstPart(controller, method, actionUrl); 
     var response = callBack(); 
     return SecondPart(response); 
    } 
} 

public class HttpResponseModelGetter<T> : RequestCreator 
{ 
    public Dictionary<String, Object> 
      GetActionResponse(ApiController controller,HttpMethod method, 
       String actionUrl,Func<T,HttpResponseMessage> callBack,T param) 
    { 
     FirstPart(controller, method, actionUrl); 
     var response = callBack(param); 
     return SecondPart(response); 
    } 
} 

public class HttpResponseModelGetter<T1,T2> : RequestCreator 
{ 
    public Dictionary<String, Object> 
     GetActionResponse(ApiController controller,HttpMethod method, 
      String actionUrl,Func<T1,T2,HttpResponseMessage> callBack, 
      T1 param1,T2 param2) 


    { 
     FirstPart(controller, method, actionUrl); 
     var response = callBack(param1,param2); 
     return SecondPart(response); 
    } 
} 
//and so on... 

y uso:

var responseGetter = new HttpResponseModelGetter(); 
var result = responseGetter.GetActionResponse(controller,HttpMethod.Get, 
        "http://localhost/Project/api/MyControllerApi/SomeApiMethod", 
               controller.SomeApiMethod); 

Boolean isComplete = Boolean.Parse(result["isComplete"].ToString()); 
1

Usando AutoFixture, por lo general hacer algo como esto:

[Theory, AutoCatalogData] 
public void PostToCollectionReturnsCorrectResponse(
    CategoriesController sut, 
    CategoryRendition categoryRendition) 
{ 
    HttpResponseMessage response = sut.Post(categoryRendition); 

    Assert.Equal(HttpStatusCode.Created, response.StatusCode); 
} 

Ver this other SO answer para más detalles acerca de este enfoque. código

+0

@Downvoter ¿Le importa explicar el problema? –

0

de muestra para el regulador API unidad de pruebas con fundtion asíncrono en C#

  1. Prepare modelos de prueba:

     using System; 
         namespace TestAPI.Models 
         { 
          public class TestResult 
          { 
           public DateTime Date { get; set; } 
           public bool Success { get; set; } 
           public string Message { get; set; } 
          }  
         } 
    
  2. Preparar controlador de ensayo

     using TestAPI.Models; 
         using System; 
         using System.Net; 
         using System.Threading.Tasks; 
         using System.Web.Http; 
         using System.Web.Http.Description; 
    
         namespace TestAPI.Controllers 
         { 
          public class TestController : ApiController 
          {  
           public TestController() 
           {   
           } 
    
           [HttpPost] 
           [ResponseType(typeof(TestResult))] 
           [Route("api/test/start")] 
           public async Task<IHttpActionResult> StartTest() 
           {         
            DateTime startTime = DateTime.Now; 
            var testProcessor = new TestAsync(); 
            await testProcessor.StartTestAsync();          
    
            HttpStatusCode statusCode = HttpStatusCode.OK; 
            return Content(statusCode, new TestResult 
            { 
             Date = DateTime.Now, 
             Success = true, 
             Message = "test" 
            }); 
           }  
    
          } 
         } 
    
  3. unidad de controlador asíncrono prueba con el resultado de la respuesta

     using Microsoft.VisualStudio.TestTools.UnitTesting; 
         using TestAPI.Controllers; 
         using TestAPI.Models; 
         using System.Web.Http; 
         using System.Threading.Tasks; 
         using System.Net; 
         using System.Web.Script.Serialization; 
    
         namespace Unit.Tests.Controllers 
         { 
          /// <summary> 
          /// Summary description for ControllerTest 
          /// </summary> 
          [TestClass] 
          public class ControllerTest 
          { 
           private TestController _testController;  
           [TestInitialize] 
           public void estAPI_Initializer() 
           { 
            _testController = new TestController(); 
            var configuration = new HttpConfiguration(); 
            System.Net.Http.HttpRequestMessage request = new System.Net.Http.HttpRequestMessage(); 
            request.Headers.Add("Authorization", "Bearer 1232141241"); 
            request.Headers.Add("ContentType", "application/json"); 
            _testController.Request = request; 
            _testController.Configuration = configuration;    
           } 
    
           [TestCategory("Unit test")] 
           [TestMethod] 
           public async Task API_Async_Controller_Test() 
           { 
            IHttpActionResult asyncResponse = await _testController.StartTest(); 
            var cToken = new System.Threading.CancellationToken(true);   
            var rResult = asyncResponse.ExecuteAsync(cToken);      
            Assert.IsNotNull(rResult); 
            Assert.IsNotNull(rResult.Result); 
            Assert.AreEqual(rResult.Result.StatusCode, HttpStatusCode.OK); 
            Assert.IsNotNull(rResult.Result.Content); 
            var rContent = rResult.Result.Content; 
    
            string data = await rContent.ReadAsStringAsync(); 
            Assert.IsNotNull(data); 
            JavaScriptSerializer JSserializer = new JavaScriptSerializer(); 
            var finalResult = JSserializer.Deserialize<TestResult>(data); 
    
            Assert.IsNotNull(finalResult); 
            Assert.IsTrue(finalResult.Success); 
           }   
          } 
         } 
    
Cuestiones relacionadas