2014-05-07 5 views
5

Voglio creare un'istanza di FormsAuthenticationTicket (su cui non ho controllo, parte di System.Web.Security) utilizzando Autofixture E assicurandomi che il Data utente (di tipo string) contiene una stringa XML validoCreare un'istanza di FormsAuthenticationTicket con una stringa XML valida in UserData

var testTicket = fixture.Create<FormsAuthenticationTicket>(); 

il problema è che UserData può essere impostato solo quando un'istanza dell'oggetto utilizzando il seguente costruttore:

public FormsAuthenticationTicket(int version, string name, DateTime issueDate, DateTime expiration, bool isPersistent, string userData); 

Dove "userData" è una stringa XML valido.

Posso configurare questo tipo per utilizzare il costruttore più avido, ma questo non risolve il problema di fornire una stringa XML valida a userData.

Potrei bloccare il tipo di stringa per far sì che restituisca sempre una stringa XML valida, ma mi interessano anche altri valori di stringa sul mio test.

Sto pensando che un possibile approccio sia la personalizzazione dell'algoritmo per la generazione di stringhe ... ma non ho parametri per sapere quando fornire la stringa XML.

risposta

2

AutoFixture raccoglie il costruttore modesta (per impostazione predefinita) e dal momento che userData non fa parte del costruttore modesta abbiamo bisogno di personalizzare due cose qui:

  1. Modificare la strategia di costruzione per un singolo tipo (FormsAuthenticationTicket).
  2. Fornire un valore personalizzato all'argomento costruttore userData.

Il seguente personalizzazione incapsula entrambi:

internal class UserDataCustomization : ICustomization 
{ 
    private readonly string userData; 

    public UserDataCustomization(string userData) 
    { 
     this.userData = userData; 
    } 

    public void Customize(IFixture fixture) 
    { 
     fixture.Customize<FormsAuthenticationTicket>(c => 
      c.FromFactory(
       new MethodInvoker(
        new GreedyConstructorQuery()))); 
     fixture.Customizations.Add(new UserDataBuilder(this.userData)); 
    } 

    private class UserDataBuilder : ISpecimenBuilder 
    { 
     private readonly string userData; 

     public UserDataBuilder(string userData) 
     { 
      this.userData = userData; 
     } 

     public object Create(object request, ISpecimenContext context) 
     { 
      var pi = request as ParameterInfo; 
      if (pi != null && pi.Name == "userData") 
       return this.userData; 

      return new NoSpecimen(); 
     } 
    } 
} 

Il seguente test passa:

[Fact] 
public void UserDataIsCorrect() 
{ 
    var expected = "<foo></foo>"; 
    var fixture = new Fixture(); 
    fixture.Customize(new UserDataCustomization(expected)); 

    var actual = fixture.Create<FormsAuthenticationTicket>(); 

    Assert.Equal(expected, actual.UserData); 
} 

Speranza che aiuta.


FWIW, qui è anche lo stesso in F #:

open Ploeh.AutoFixture 
open Ploeh.AutoFixture.Kernel 
open System 
open System.Reflection 
open System.Web.Security 

type UserDataCustomization (userData) = 
    let builder = { 
     new ISpecimenBuilder with 
      member this.Create(request, context) = 
       match request with 
       | :? ParameterInfo as pi 
        when pi.Name = "userData" -> box userData 
       | _ -> NoSpecimen request |> box } 

    interface ICustomization with 
     member this.Customize fixture = 
      fixture.Customize<FormsAuthenticationTicket>(fun c -> 
       c.FromFactory(
        MethodInvoker(
         GreedyConstructorQuery())) :> ISpecimenBuilder) 
      fixture.Customizations.Add builder 

Il seguente test passa:

open Xunit 
open Swensen.Unquote.Assertions 

[<Fact>] 
let UserDataIsCorrect() = 
    let expected = "<foo></foo>" 
    let fixture = Fixture().Customize(UserDataCustomization(expected)) 

    let actual = fixture.Create<FormsAuthenticationTicket>() 

    test <@ expected = actual.UserData @> 
2

Il congelamento della stringa funzionerebbe, ma non è auspicabile poiché interesserebbe anche tutte le altre stringhe generate.

Io uso questa classe per personalizzare uno specifico argomento del costruttore:

public class GenericArgCustomization<T> : ISpecimenBuilder 
{ 
    private readonly string name; 
    private readonly T value; 

    public GenericArgCustomization(string name, T value) 
    { 
     if (String.IsNullOrEmpty(name)) 
      throw new ArgumentException("Name is required", "name"); 

     this.name = name; 
     this.value = value; 
    } 

    public object Create(object request, ISpecimenContext context) 
    { 
     var pi = request as ParameterInfo; 
     if (pi == null) 
      return new NoSpecimen(request); 

     if (pi.ParameterType != typeof(T) || pi.Name != this.name) 
      return new NoSpecimen(request); 

     return this.value; 
    } 
} 

Successivamente, è possibile utilizzarla specificando il tipo generico (string in questo caso) e il nome argomento del costruttore che si desidera personalizzare (userData in questo caso). Questo è case-sensitive, quindi corrisponde al nome dell'argomento che hai usato nella classe.

Esempio:

var xml = "<root>My Valid XML Value Here</root>"; 
var customUserData = new GenericArgCustomization<string>("userData", xml); 
var fixture = new Fixture(); 
fixture.Customizations.Add(customUserData); 
var item = fixture.Create<FormsAuthenticationTicket>(); 

Ora l'oggetto viene creato con dati quali:

  • Versione: 85
  • Nome: name1e8fb8b1-5879-4256-8729-ca6afeb1bd80
  • Data di Rilascio: 12/3/2015 8:00:05 AM
  • IsPersistent: True
  • UserData: <root>My Valid XML Value Here</root>
+1

Anche se questo è un bell'aspetto come un approccio generalizzato, in questo caso particolare non funzionerà perché 'userData' non fa parte del costruttore modesto. –

+0

@Nikos che è giusto precisare. L'OP ha menzionato l'aver familiarizzato con l'impostazione di una ingombrante personalizzazione del costruttore, quindi non ho ribadito questa parte. –

+1

concordato. Ma personalmente preferisco risposte autonome in cui puoi facilmente copiare e incollare la risposta e usarla. Gli utenti leggono raramente le pagine Web parola per parola; invece, [scandiscono la pagina] (http://www.nngroup.com/articles/how-users-read-on-the-web/). –

Problemi correlati