A AutoFixture pode executar um delegado no momento da criação do object?

Eu estou olhando para personalizar o comportamento de tempo de criação de AutoFixture de modo que eu possa configurar alguns objects dependentes após as propriedades do equipamento terem sido geradas e atribuídas.

Por exemplo, suponha que eu tenha um método que personalize um User porque sua propriedade IsDeleted sempre tem que ser falsa para um determinado conjunto de testes:

 public class User { public int Id { get; set; } public string Name { get; set; } public bool IsDeleted { get; set; } } public static ObjectBuilder BuildUser(this Fixture f) { return f.Build().With(u => u.IsDeleted, false); } 

(Eu entrego um ObjectBuilder volta ao teste para que ele possa personalizar ainda mais o equipamento, se necessário.)

O que eu gostaria de fazer é associar automaticamente esse usuário com uma coleção anônima por seu Id no momento da criação, mas não posso fazer isso como está, porque o Id não foi gerado no momento em que entrego o valor de retorno de volta ao teste de unidade adequado. Aqui está o tipo de coisa que estou tentando fazer:

 public static ObjectBuilder BuildUserIn(this Fixture f, UserCollection uc) { return f.Build() .With(u => u.IsDeleted, false); .AfterCreation(u => { var relation = f.Build() .With(ucm => ucm.UserCollectionId, uc.Id) .With(ucm => ucm.UserId, u.Id) .CreateAnonymous(); Repository.Install(relation); } } 

É algo assim possível? Ou talvez exista uma maneira melhor de atingir meu objective de criar um gráfico de object anônimo?

Para o método Build , isso não é possível e provavelmente nunca será, porque há opções muito melhores disponíveis.

Em primeiro lugar, nunca deve ser necessário escrever methods auxiliares estáticos em torno do método Build . O método Build é para inicializações verdadeiramente únicas em que é necessário definir valores de propriedade ou campo antes do fato.

Imagine uma aula assim:

 public class MyClass { private string txt; public string SomeWeirdText { get { return this.txt; } set { if (value != "bar") throw new ArgumentException(); this.txt = value; } } } 

Neste exemplo, um straight fixture.CreateAnonymous será lançado porque tentará atribuir algo diferente de “bar” à propriedade.

Em um cenário único, pode-se usar o método Build para escaping desse problema. Um exemplo é simplesmente definir o valor explicitamente como “bar”:

 var mc = fixture.Build().With(x => x.SomeWeirdText, "bar").CreateAnonymous(); 

No entanto, ainda mais fácil seria omitir essa propriedade:

 var mc = fixture.Build().Without(x => x.SomeWeirdText).CreateAnonymous(); 

No entanto, quando você começar a querer fazer isso repetidamente, existem opções melhores. O AutoFixture tem um mecanismo muito sofisticado e personalizável para definir como as coisas são criadas.

Para começar, pode-se começar movendo a omissão da propriedade para uma customização, como esta:

 fixture.Customize(c => c.Without(x => x.SomeWeirdText)); 

Agora, sempre que o equipamento criar uma instância do MyClass, ele simplesmente ignorará essa propriedade. Você ainda pode atribuir um valor depois:

 var mc = fixture.CreateAnonymous(); my.SomeWeirdText = "bar"; 

Se você quiser algo mais sofisticado, você pode implementar um ISpecimenBuilder personalizado . Se você quiser executar algum código personalizado após a criação da instância, poderá decorar seu próprio ISpecimenBuilder com um Pós-processador e fornecer um representante. Isso pode parecer algo assim:

 fixture.Customizations.Add( new Postprocessor(yourCustomSpecimenBuilder, obj => { */ do something to obj here */ })); 

(BTW, você ainda está no AutoFixture 1.0? IIRC, não existe um ObjectBuilder desde então …)

Há uma discussão útil sobre esse tópico no site AutoPixture CodePlex .

Acredito que minha Personalização de pós-processamento vinculada por lá deve ajudá-lo. Exemplo de uso:

 class AutoControllerDataAttribute : AutoDataAttribute { public AutoControllerDataAttribute() : this( new Fixture() ) { } public AutoControllerDataAttribute( IFixture fixture ) : base( fixture ) { fixture.Customize( new AutoMoqCustomization() ); fixture.Customize( new ApplyControllerContextCustomization() ); } class ApplyControllerContextCustomization : PostProcessWhereIsACustomization { public ApplyControllerContextCustomization() : base( PostProcess ) { } static void PostProcess( Controller controller ) { controller.FakeControllerContext(); // etc. - add stuff you want to happen after the instance has been created 
Intereting Posts