tutorial maphttproute example ejemplo c# autofixture automoq

c# - maphttproute - Automocking Web Api 2 controlador



web api rest c# tutorial (3)

Basado en la respuesta de Nikos:

Esta es una forma más genérica de usar esta personalización donde se puede suministrar el tipo de controlador y se puede usar la Customization para cualquier controlador.

internal class WebApiCustomization<TControllerType> : ICustomization where TControllerType : ApiController { public void Customize(IFixture fixture) { fixture.Customize<HttpRequestMessage>(c => c .Without(x => x.Content) .Do(x => x.Properties[HttpPropertyKeys.HttpConfigurationKey] = new HttpConfiguration())); fixture.Customize<TControllerType>(c => c .OmitAutoProperties() .With(x => x.Request, fixture.Create<HttpRequestMessage>())); } }

A continuación, utilice de la siguiente manera:

var fixture = new Fixture().Customize( new WebApiCustomization<UsersController>()); var sut = fixture.Create<UsersController>();

Estoy intentando simular automáticamente la clase ApiController en mis casos de prueba. Funcionó perfectamente cuando estaba usando WebApi1. Comencé a usar WebApi2 en el nuevo proyecto y recibo esta excepción después de que intento ejecutar mis nuevas pruebas:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Security.Cryptography.CryptographicException: pCertContext is an invalid handle. at System.Security.Cryptography.CAPI.CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, UInt32 dwPropId, UInt32 dwFlags, SafeLocalAllocHandle safeLocalAllocHandle) at System.Security.Cryptography.X509Certificates.X509Certificate2.set_Archived(Boolean value)

Mi código de prueba:

[Theory, AutoMoqData] public void approparte_status_code_is_returned( string privateKey, UsersController sut) { var response = sut.GetUser(privateKey); var result = response; Assert.Equal(HttpStatusCode.OK, result.StatusCode); }

El caso de prueba funciona si creo sut manualmente:

[Theory, AutoMoqData] public void approparte_status_code_is_returned( string privateKey, [Frozen]Mock<IUserModel> stubModel) { var sut = new UsersController(stubModel.Object); var response = sut.GetUser(privateKey); var result = response; Assert.Equal(HttpStatusCode.OK, result.StatusCode); }

Parece que algo sale mal al intentar simular el ControllerContext.RequestContext.ClientCertificate He intentado crear un dispositivo sin él (utilizando el método AutoFixture .Without ()) pero incluso las pruebas anteriores empezaron a fallar.

Mi AutoMoqDataAttribute:

public class AutoMoqDataAttribute : AutoDataAttribute { public AutoMoqDataAttribute() : base(new Fixture() .Customize(new WebApiCustomization())) { } }

Personalización de WebApi:

public class WebApiCustomization : CompositeCustomization { public WebApiCustomization() : base( new HttpRequestMessageCustomization(), new AutoMoqCustomization()) { } }

Personalización de HttpRequestMessage:

public class HttpRequestMessageCustomization : ICustomization { public void Customize(IFixture fixture) { fixture.Customize<HttpRequestMessage>(c => c .Without(x => x.Content) .Do(x => { x.Properties[HttpPropertyKeys.HttpConfigurationKey] = new HttpConfiguration(); }) ); } }

Controlador de usuarios:

/// <summary> /// Handles user''s account. /// </summary> [RoutePrefix("api/v1/users/{privateKey:length(64)}")] public class UsersController : ApiController { private readonly IUserModel _model; public UsersController(IUserModel model) { _model = model; } /// <summary> /// Returns a user. /// </summary> /// <param name="privateKey">The private key of the user.</param> /// <returns> /// 200 (OK) with user data is returned when user is found. /// 404 (Not found) is returned when user is not found. /// </returns> [HttpGet] [Route("")] public HttpResponseMessage GetUser(string privateKey) { UserProjection projection; try { projection = new UserProjection(_model.Get(privateKey)); } catch (UserNotFoundException) { return new HttpResponseMessage(HttpStatusCode.NotFound); } return Request.CreateResponse(HttpStatusCode.OK, projection); } }


Nota : La answer original requiere que se copie la misma personalización para cada ApiController nuevo.

Enfoque generalizado

Una forma alternativa es rellenar automáticamente la propiedad de Request en todos los ApiControllers (lo que le ahorra cortes, copiar y pegar):

internal class ApiControllerCustomization : ICustomization { public void Customize(IFixture fixture) { fixture.Customizations.Add( new FilteringSpecimenBuilder( new Postprocessor( new MethodInvoker( new ModestConstructorQuery()), new ApiControllerFiller()), new ApiControllerSpecification())); } private class ApiControllerFiller : ISpecimenCommand { public void Execute(object specimen, ISpecimenContext context) { if (specimen == null) throw new ArgumentNullException("specimen"); if (context == null) throw new ArgumentNullException("context"); var target = specimen as ApiController; if (target == null) throw new ArgumentException( "The specimen must be an instance of ApiController.", "specimen"); target.Request = (HttpRequestMessage)context.Resolve( typeof(HttpRequestMessage)); } } private class ApiControllerSpecification : IRequestSpecification { public bool IsSatisfiedBy(object request) { var requestType = request as Type; if (requestType == null) return false; return typeof(ApiController).IsAssignableFrom(requestType); } } }

El valor de tipo HttpRequestMessage , para la propiedad Request , se construye usando la siguiente personalización:

internal class HttpRequestMessageCustomization : ICustomization { public void Customize(IFixture fixture) { fixture.Customize<HttpRequestMessage>(c => c .Without(x => x.Content) .Do(x => x.Properties[HttpPropertyKeys.HttpConfigurationKey] = new HttpConfiguration())); } }

Embalaje todo en una personalización compuesta

Cree un compuesto de personalización como se indica a continuación: tenga en cuenta que el orden de las personalizaciones de AutoFixture es importante :

internal class ApiControllerConventions : CompositeCustomization { internal ApiControllerConventions() : base( new HttpRequestMessageCustomization(), new ApiControllerCustomization(), new AutoMoqCustomization()) { } }

Espero que ayude.


Nota : Suponiendo que la clase UserController toma un IUserModel través de su constructor.

Tal como parece, el constructor predeterminado de ApiController realiza algunos trabajos (probablemente más que simples tareas).

Si la clase UserController lleva un IUserModel través de su constructor, puede elegir ese constructor (el más codicioso ) en su lugar .

Actualización :

Reemplace la personalización HttpRequestMessageCustomization con:

internal class ApiControllerCustomization : ICustomization { public void Customize(IFixture fixture) { fixture.Customize<HttpRequestMessage>(c => c .Without(x => x.Content) .Do(x => x.Properties[HttpPropertyKeys.HttpConfigurationKey] = new HttpConfiguration())); fixture.Customize<UsersController>(c => c .OmitAutoProperties() .With(x => x.Request, fixture.Create<HttpRequestMessage>())); } }

Y la prueba original se ejecutará bien.