铸造

编辑该页面

铸造

铸造支持教义/ orm(与教义/ doctrine-bundle),教义/ mongodb-odm(与教义/ mongodb-odm-bundle)或两者结合。

安装

1
美元作曲家需要zenstruck /铸造- dev

使用:*命令从这个包,确保ob娱乐下载Symfony MakerBundle安装。

如果不使用Symfony ob娱乐下载Flex,务必使你的包测试/dev环境。

相同的实体中使用这些文档

其余的文档,将使用以下示例实体:欧宝官网下载app

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27日28
名称空间应用程序\实体;使用学说\ORM\映射作为ORM;/ * * *@ORM实体(repositoryClass = \ App \ Repository \ CategoryRepository) * /类别{/ * * *@ORM* \ Id ()@ORM* \ GeneratedValue ()@ORM\列(类型=“整数”)* /私人美元id;/ * * *@ORM\列(类型=“字符串”,长度= 255)* /私人美元的名字;公共函数__construct(字符串美元的名字){美元- >name =美元的名字;}/ /……getter / setter}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
名称空间应用程序\实体;使用学说\ORM\映射作为ORM;/ * * *@ORM实体(repositoryClass = \ App \ Repository \ PostRepository) * /帖子{/ * * *@ORM* \ Id ()@ORM* \ GeneratedValue ()@ORM\列(类型=“整数”)* /私人美元id;/ * * *@ORM\列(类型=“字符串”,长度= 255)* /私人美元标题;/ * * *@ORM\列(type = " text ",可空= true) * /私人美元身体;/ * * *@ORM\列(type = " datetime) * /私人美元createdAt;/ * * *@ORM\列(type = " datetime, nullable = true) * /私人美元publishedAt;/ * * *@ORM\ ManyToOne (targetEntity =类别::类)*@ORM\ JoinColumn * /私人美元类别;公共函数__construct(字符串美元标题){美元- >title =美元标题;美元- >createdAt =\ DateTime (“现在”);}/ /……getter / setter}

模型的工厂

最好的用铸造的方法是生成一个工厂每个实体类。你可以跳过这和使用匿名的工厂,但模型的工厂给你IDE自动完成和获取其他有用的特性。

生成

创建一个模型你的一个实体的工厂和制造商命令:

1 2 3 4 5 6 7 8
美元bin /控制台:工厂>实体类创建一个工厂:> Post创建:src /工厂/ PostFactory。php:打开你的新工厂默认值/状态。

这个命令将生成一个PostFactory这样的类:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
/ / src /工厂/ PostFactory.php名称空间应用程序\工厂;使用应用程序\实体\帖子;使用应用程序\存储库\PostRepository;使用Zenstruck\铸造\RepositoryProxy;使用Zenstruck\铸造\ModelFactory;使用Zenstruck\铸造\代理;/ * * *@extendsModelFactory <邮报> * *@method静态代理createOne邮报|(数组$属性= [])*@method静态发布代理[][]| createMany (int数美元,数组|可调用$属性= [])*@method静态发布[]代理[]createSequence(数组|可调用的序列美元)*@method静态发布|代理找到(数组对象| |混合标准美元)*@method静态发布|代理findOrCreate(数组属性)美元*@method静态发布|代理第一(字符串$ sortedField =“id”) *@method静态发布|代理去年(字符串$ sortedField =“id”) *@method静态发布|代理随机(数组$属性= [])*@method静态代理randomOrCreate邮报|(数组$属性= []))*@method静态发布代理[][]|所有()*@method将其作为findBy静态发布代理[][]|(数组属性)美元*@method静态发布代理[][]| randomSet (int数美元,数组$属性= []))*@method静态发布代理[][]| randomRange (int分钟美元,int马克斯美元,数组$属性= []))*@method静态PostRepository | RepositoryProxy库()*@method邮报|代理创建(数组|可调用$属性= [])* /最后PostFactory扩展ModelFactory{/ * * *@seehttps://github.com/zenstruck/foundry factories-as-services * *@todo如果需要* /注射服务公共函数__construct(){::__construct ();}/ * * *@seehttps://github.com/zenstruck/foundry模范工厂* *@todo在此处添加您的默认值* /受保护的函数getDefaults():数组{返回[];}/ * * *@seehttps://github.com/zenstruck/foundry初始化* /受保护的函数初始化():自我{返回美元/ / - > afterInstantiate(函数(美元){});}受保护的静态函数getClass():字符串{返回帖子::类;}}

提示

使用:工厂——测试将生成的工厂吗测试/工厂

请注意

生成的@methoddocblocks之上启用自动完成与PhpStorm但是PHPStan导致错误。支持PHPStan贵厂的,你需要添加以下dockblocks:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21日22日23日
/ * * *……* *@phpstan方法代理<邮报>创建(数组|可调用$属性= [])*@phpstan方法静态代理<邮报> createOne(数组$属性= [])*@phpstan静态代理方法<邮报>找到(数组对象| |混合标准美元)*@phpstan静态代理方法<邮报> findOrCreate(数组属性)美元*@phpstan静态代理方法<邮报>第一(字符串$ sortedField =“id”) *@phpstan去年(string方法静态代理<邮报> $ sortedField =“id”) *@phpstan方法静态代理<邮报>随机(数组$属性= [])*@phpstan方法静态代理<邮报> randomOrCreate(数组$属性= [])*@phpstan方法静态列表<代理<邮报> > ()*@phpstan方法静态列表<代理<邮报> > createMany (int数美元,数组|可调用$属性= [])*@phpstan方法静态列表<代理<邮报> > createSequence(数组|可调用的序列美元)*@phpstan将其作为findBy方法静态列表<代理<邮报> >(数组属性)美元*@phpstan方法静态列表<代理<邮报> > randomRange (int分钟美元,int马克斯美元,数组$属性= [])*@phpstan方法静态列表<代理<邮报> > randomSet (int数美元,数组$属性= [])*@phpstan方法静态RepositoryProxy <邮报>存储库()* /最后PostFactory扩展ModelFactory{/ /……}

getDefaults (),你可以返回一个数组的默认值,任何新对象。骗子可以很容易地得到随机数据:

1 2 3 4 5 6 7 8 9
受保护的函数getDefaults():数组{返回(/ /ob娱乐下载 Symfony的属性访问组件用于填充属性/ /这意味着setTitle()或美元你可以有一个构造函数参数“标题”= >自我::骗子()- >独特的()- >句子(),“身体”= >自我::骗子()- >句子()];}

提示

它是最好的getDefaults ()返回属性持续有效的对象(所有非空字段)。

提示

使用:工厂——所有字段将生成实体的所有字段的默认值,不仅非空字段。

使用你的工厂

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
使用应用程序\工厂\PostFactory;/ /创建/保存后的随机数据的getDefaults ()”PostFactory::createOne ();/ /或者提供一些属性的值(别人会随机)PostFactory::createOne ([“标题”= >“我的名字”]);/ / createOne()返回持久化对象包装在一个代理对象美元帖子= PostFactory::createOne ();/ /“代理”神奇地调用底层Post方法,type-hinted“发布”美元标题=美元帖子- >getTitle ();/ / getTitle()可以通过IDE自动完成!/ /如果你需要实际的对象,使用- >对象()美元realPost=美元帖子- >对象();/ /创建/持续5文章从getDefaults随机数据()PostFactory::createMany (5);/ /返回邮政代理[][]|PostFactory::createMany (5,(“标题”= >“我的名字”]);/ /用增量创建5个帖子标题PostFactory::createMany (5,静态函数(int美元){返回(“标题”= >“标题我美元”];/ /“标题1”、“标题2”,……“标题5”});/ /找到一个持久化对象给定属性,如果没有找到,创建的属性PostFactory::findOrCreate ([“标题”= >“我的名字”]);/ /返回帖子|代理PostFactory::第();/ /获得第一个对象(假设一个自动递增的“id”列)PostFactory::第一次(“createdAt”);/ /假设“createdAt”是一个datetime列,这将返回最新的对象PostFactory::最后();/ /得到最后一个对象(假设一个自动递增" id "列)PostFactory::最后一个(“createdAt”);/ /假设“createdAt”是一个datetime列,这将返回古老的对象PostFactory::截断();/ /清空数据库表中PostFactory::count ();/ /保存帖子的数量PostFactory::所有();/ /发布代理[][]|保存文章PostFactory::findBy ([“作者”= >“凯文”]);/ /发布代理[][]|匹配滤波器美元帖子= PostFactory::找到(5);/ /发布| 5代理的id美元帖子= PostFactory::找到([“标题”= >“我的第一个帖子”]);/ /发布|代理匹配滤波器/ /得到一个随机的对象,一直坚持美元帖子= PostFactory::随机();/ /返回帖子|代理美元帖子= PostFactory::随机([“作者”= >“凯文”]);/ /通过过滤器的属性/ /或自动保存一个新的随机对象如果没有存在美元帖子= PostFactory::randomOrCreate ();美元帖子= PostFactory::randomOrCreate ([“作者”= >“凯文”]);/ /过滤或创造与传递的属性/ /获得一个随机设置的对象持久化美元的帖子= PostFactory::randomSet (4);/ /数组包含4“后|代理”对象美元的帖子= PostFactory::randomSet (4,(“作者”= >“凯文”]);/ /通过过滤器的属性/ /随机持久化对象的范围美元的帖子= PostFactory::randomRange (0,5);/ /数组包含0 - 5“后|代理”对象美元的帖子= PostFactory::randomRange (0,5,(“作者”= >“凯文”]);/ /通过过滤器的属性

可重用模型工厂“州”

您可以添加任何你想要的方法你的模型工厂(即静态方法创建一个对象以某种方式),但你也可以添加:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27
名称空间应用程序\工厂;使用应用程序\实体\帖子;使用Zenstruck\铸造\ModelFactory;最后PostFactory扩展ModelFactory{/ /……公共函数发表():自我{/ /调用setPublishedAt(),通过一个随机DateTime返回美元- >addState ([“published_at”= >自我::骗子()- >dateTime ()));}公共函数未发表的():自我{返回美元- >addState ([“published_at”= >]);}公共函数withViewCount(int美元= null):自我{返回美元- >addState (函数()使用(美元){返回(“view_count”= >美元? ?自我::骗子()- >numberBetween (0,10000年));});}}

您可以使用状态让你测试改善可读性非常明确:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/ /不使用构造函数(即。“新PostFactory()”),但使用/ /新()方法。定义状态后,叫“create()”创建/ /和持久存储模型。美元帖子= PostFactory::()- >未发表的()- >create ();美元帖子= PostFactory::()- >withViewCount (3)- >create ();/ /合并多个州美元帖子= PostFactory::()- >未发表的()- >withViewCount (10)- >create ();/ /州不需要参数可以作为字符串添加PostFactory::新()美元帖子= PostFactory::(“发布”,“withViewCount”)- >create ();

属性

用于实例化对象的属性可以添加几个方面。属性可以是一个数组,或者一个可调用的返回一个数组。使用一个可调用的确保随机数据的调用期间单独运行每个对象实例化。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36
使用应用程序\实体\类别;使用应用程序\实体\帖子;使用应用程序\工厂\CategoryFactory;使用应用程序\工厂\PostFactory;使用函数Zenstruck\铸造\骗子;/ /第一个参数“新()”允许您覆盖默认值/ /值定义在“PostFactory: getDefaults ()”美元的帖子= PostFactory::([“标题”= >“发布”])- >withAttributes ([“身体”= >“帖子的身体…”,/ / CategoryFactory将用于创建一个新的类别为每个职位“类别”= > CategoryFactory::([“名字”= >“php”))))- >withAttributes ([/ /代理自动转化为他们的包装对象“类别”= > CategoryFactory::createOne ())- >withAttributes (函数(){返回(“createdAt”= >骗子()- >dateTime ()];})/ /下面看到摊贩部分/ /创建邮政的“2”- >许多(2)- >创建([“标题”= >“不同的标题”]);美元的帖子(0]- >getTitle ();/ /“不同的标题”美元的帖子(0]- >getBody ();/ /“后的身体……”美元的帖子(0]- >getCategory ();/ /随机类别美元的帖子(0]- >getPublishedAt ();/ / \ DateTime(上周)美元的帖子(0]- >getCreatedAt ();/ /随机\ DateTime美元的帖子(1]- >getTitle ();/ /“不同的标题”美元的帖子(1]- >getBody ();/ /“后的身体……”美元的帖子(1]- >getCategory ();/ /随机类别(不同于上图)美元的帖子(1]- >getPublishedAt ();/ / \ DateTime(上周)美元的帖子(1]- >getCreatedAt ();/ /随机\ DateTime(不同于上图)

请注意

属性传递给创建*方法是与任何属性设置通过合并getDefaults ()withAttributes ()

序列

序列有助于创建不同的对象在一个调用:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27日28
使用应用程序\工厂\PostFactory;/ /创建/持续2文章基于一系列的属性PostFactory::createSequence ([[“名字”= >“标题1”]、[“名字”= >“标题2”)));/ /创建10个帖子用一系列回调增量索引PostFactory::createSequence (函数(){foreach(范围(1,10)作为美元){收益率(“名字”= >“标题我美元”];}});/ /序列也可以使用一个工厂与状态美元的帖子= PostFactory::()- >未发表的()- >序列([[“名字”= >“标题1”]、[“名字”= >“标题2”),)- >create ();

骗子

这个库提供了一个包装器FakerPHP为您的工厂帮助生成随机数据:

1 2 3 4 5 6 7
使用Zenstruck\铸造\工厂;使用函数Zenstruck\铸造\骗子;工厂::骗子()- >名称();/ /随机名称/ /另外,使用helper函数骗子()- >电子邮件();/ /随机邮件

请注意

你可以定制伪装者语言环境和随机种子:

1 2 3 4 5 6
#配置/包/ zenstruck_foundry.yamlwhen@dev:#包配置部分中看到的分享这个测试环境zenstruck_foundry:骗子:地区:fr_FR#设置语言环境种子:5678年#设置随机数生成器的种子

请注意

完全控制,你可以注册自己的摊贩\发电机服务:

1 2 3 4 5
#配置/包/ zenstruck_foundry.yamlwhen@dev:#包配置部分中看到的分享这个测试环境zenstruck_foundry:骗子:服务:my_faker#服务为自己的实例id的摊贩\生成器

事件/钩子

下面的事件可以被添加到工厂。可以添加多个事件回调函数,它们运行的顺序,他们补充道。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33
使用应用程序\工厂\PostFactory;使用Zenstruck\铸造\代理;PostFactory::()- >beforeInstantiate (函数(数组美元属性):数组{/ /属性就是美元将用于实例化对象,按要求操作美元属性(“标题”]=“不同的标题”;返回美元属性;/ /必须返回最后美元属性})- >afterInstantiate (函数(文章美元对象数组,美元属性):无效{/ /对象实例化对象/ /属性包含美元用来实例化对象和任何额外的属性})- >afterPersist (函数(代理美元代理数组,美元属性){/ *@var邮政代理* /美元/ /如果该对象调用这个事件只是坚持/ /美元代理是代理包装持久化对象/ /属性包含美元用来实例化对象和任何额外的属性})/ /如果第一个参数是type-hinted作为对象,它将被传递到闭包(而不是代理)- >afterPersist (函数(文章美元对象数组,美元属性){/ /如果该对象调用这个事件只是坚持/ / $对象持久化对象/ /属性包含美元用来实例化对象和任何额外的属性})/ /允许多个事件- >beforeInstantiate (函数(美元属性){返回美元属性;})- >afterInstantiate (函数(){})- >afterPersist (函数(){});

你也可以添加钩子直接在您的模型工厂类:

1 2 3 4 5 6
受保护的函数初始化():自我{返回美元- >afterPersist (函数(){});}

初始化学习更多有关初始化()方法。

初始化

你可以覆盖模型工厂的初始化()方法添加默认状态/逻辑:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
名称空间应用程序\工厂;使用应用程序\实体\帖子;使用Zenstruck\铸造\ModelFactory;最后PostFactory扩展ModelFactory{/ /……受保护的函数初始化():自我{返回美元- >(出版)/ /默认发布- >instantiateWith (函数(数组美元属性){返回Post ();/ /自定义实例化这个工厂})- >afterPersist (函数(){})/ /默认事件这个工厂;}}

请注意

一定要链状态/挂钩的这个美元因为工厂是不可变的

实例化

默认情况下,对象实例化以正常的方式,通过使用对象的构造函数。使用属性相匹配的构造函数参数。剩余的属性被设置为使用Symfony的对象ob娱乐下载PropertyAccess组件(setter /公共属性)。任何额外的属性导致抛出一个异常。

您可以定制instantiator在几个方面:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29
使用应用程序\实体\帖子;使用应用程序\工厂\PostFactory;使用Zenstruck\铸造\Instantiator;/ /设置当前工厂instantiatorPostFactory::()/ /实例化的对象而不调用构造函数- >instantiateWith ((Instantiator ())- >withoutConstructor ())/ /“foo”和“酒吧”属性实例化时被忽略- >instantiateWith ((Instantiator ())- >allowExtraAttributes ([“foo”,“酒吧”)))/ /实例化时所有额外的属性将被忽略- >instantiateWith ((Instantiator ())- >allowExtraAttributes ())/ /设置“标题”和“身体”,当实例化- >instantiateWith ((Instantiator ())- >alwaysForceProperties ([“标题”,“身体”)))/ /从不使用setter,总是“力”的特性(甚至私人/保护,不使用setter)- >instantiateWith ((Instantiator ())- >alwaysForceProperties ())/ /可以结合不同的“模式”- >instantiateWith ((Instantiator ())- >withoutConstructor ()- >allowExtraAttributes ()- >alwaysForceProperties ())/ / instantiator只是一个可调用的,你可以提供你自己的- >instantiateWith (函数(数组美元属性、字符串美元):对象{返回Post ();/ /……你自己的逻辑});

您可以定制instantiator全球所有的工厂(工厂实例instantiators仍然可以否决了):

1 2 3 4 5 6 7 8 9
#配置/包/ zenstruck_foundry.yamlwhen@dev:#包配置部分中看到的分享这个测试环境zenstruck_foundry:instantiator:without_constructor:真正的#总是没有调用构造函数实例化对象allow_extra_attributes:真正的#总是忽略额外的属性always_force_properties:真正的#总是“力”的特性#或服务:my_instantiator#为完全控制自己的调用服务

不可变的

工厂是不变的:

1 2 3 4 5 6 7 8
使用应用程序\工厂\PostFactory;美元工厂= PostFactory::();美元factory1=美元工厂- >withAttributes ([]);/ /返回一个新的PostFactory对象美元factory2=美元工厂- >instantiateWith (函数(){});/ /返回一个新的PostFactory对象美元factory3=美元工厂- >beforeInstantiate (函数(){});/ /返回一个新的PostFactory对象美元factory4=美元工厂- >afterInstantiate (函数(){});/ /返回一个新的PostFactory对象美元factory5=美元工厂- >afterPersist (函数(){});/ /返回一个新的PostFactory对象

原则的关系

假设你的实体遵循最佳实践原则的关系你正在使用的默认instantiator、铸造只是工作与原则的关系。有一些细微的差别与不同的关系和实体是如何创建的。以下为每个关系试图记录这些类型。

多对一

以下假设评论实体有一个多对一的关系帖子:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32
使用应用程序\工厂\CommentFactory;使用应用程序\工厂\PostFactory;/ /示例1:pre-create Post和附加置评美元帖子= PostFactory::createOne ();/ /代理的实例CommentFactory::createOne ([“职位”= >美元帖子]);CommentFactory::createOne ([“职位”= >美元帖子- >对象()));/ /功能上面的一样/ /示例2:pre-create帖子和选择一个随机的PostFactory::createMany (5);/ /创建5个职位CommentFactory::createOne ([“职位”= > PostFactory::随机()));/ /或创建许多,每一个都有不同的随机文章CommentFactory::createMany (5,/ /创建5个评论函数(){/ /注意回调——这可以确保每个5评论都有不同的职位返回(“职位”= > PostFactory::随机()];/ /每个评论将随机从那些已经在数据库中});/ /示例3:创建一个单独的每个评论帖子CommentFactory::createMany (5,(/ /这个属性的实例创建PostFactory分别为每一个评论“职位”= > PostFactory::()));/ /示例4:创建多个相同的帖子CommentFactory::createMany (5,(“职位”= > PostFactory::createOne (),/ /注意“createOne ()”]);

提示

你建议的唯一关系定义ModelFactory: getDefaults ()非空多对一。

提示

也建议你ModelFactory: getDefaults ()返回一个工厂而不是创建的实体:

1 2 3 4 5 6 7 8 9 10 11 12
受保护的函数getDefaults():数组{返回(/ /推荐“职位”= > PostFactory::(),“职位”= > PostFactory::()- >发表(),/ /不建议——可能会导致额外的意想不到的帖子“职位”= > PostFactory::createOne (),“职位”= > PostFactory::()- >(出版)- >create ());}

一对多

以下假设帖子实体有一对多的关系评论:

1 2 3 4 5 6 7 8 9 10 11
使用应用程序\工厂\CommentFactory;使用应用程序\工厂\PostFactory;/ /示例1:创建一个注释6PostFactory::createOne ([“评论”= > CommentFactory::()- >许多(6)));/ /例2:创建6帖子每4评论评论(24)PostFactory::createMany (6,(“评论”= > CommentFactory::()- >许多(4)));/ /示例3:创建6帖子每个介于0和10评论PostFactory::createMany (6,(“评论”= > CommentFactory::()- >许多(0,10)));

多对多

以下假设帖子实体有一个多对多的关系标签:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33
使用应用程序\工厂\PostFactory;使用应用程序\工厂\TagFactory;/ /示例1:pre-create标签和附加到职位美元标签= TagFactory::createMany (3);PostFactory::createOne ([“标签”= >美元标签]);/ /示例2:pre-create标记和选择一个随机的设置TagFactory::createMany (10);PostFactory::()- >许多(5)/ /创建5个职位- >创建(函数(){/ /注意回调——这可以确保每个5职位有不同的随机集返回(“标签”= > TagFactory::randomSet (2));/ /每个帖子使用2随机标记从那些已经在数据库中});/ /示例3:pre-create标记和选择一个随机的范围TagFactory::createMany (10);PostFactory::()- >许多(5)/ /创建5个职位- >创建(函数(){/ /注意回调——这可以确保每个5职位有不同的随机范围返回(“标签”= > TagFactory::randomRange (0,5));/ /每个帖子使用0到5之间随机标记从那些已经在数据库中});/ /例4:创建3文章每3独特的标签PostFactory::createMany (3,(“标签”= > TagFactory::()- >许多(3)));/ /例5:创建3个帖子每个以0和3之间独特的标记PostFactory::createMany (3,(“标签”= > TagFactory::()- >许多(0,3)));

工厂为服务

如果你的工厂需要依赖项,您可以定义服务。下面的例子展示了一个非常常见的用例:编码的密码UserPasswordHasherInterface服务。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
/ / src /工厂/ UserFactory.php名称空间应用程序\工厂;使用应用程序\实体\用户;使用ob娱乐下载\组件\PasswordHasher\切肉机\UserPasswordHasherInterface;使用Zenstruck\铸造\ModelFactory;最后UserFactory扩展ModelFactory{私人美元passwordHasher;公共函数__construct(UserPasswordHasherInterface美元passwordHasher){::__construct ();美元- >passwordHasher =美元passwordHasher;}受保护的函数getDefaults():数组{返回(“电子邮件”= >自我::骗子()- >独特的()- >safeEmail (),“密码”= >“1234”,);}受保护的函数初始化():自我{返回美元- >afterInstantiate (函数(用户美元用户){美元用户- >向setPassword (美元- >passwordHasher- >hashPassword (美元用户,美元用户- >getPassword ()));});}受保护的静态函数getClass():字符串{返回用户::类;}}

如果使用一个标准的Symfony Fleob娱乐下载x应用程序,这将是autowired / autoconfigure。如果没有,注册服务和标签foundry.factory

使用工厂正常:

1 2
UserFactory::createOne ([“密码”= >“mypass”])- >getPassword ();/ /“mypass”编码UserFactory::createOne ()- >getPassword ();/ /“1234”编码(因为“1234”设置为默认密码)

请注意

包需要工厂提供服务。

请注意

如果使用:工厂——测试,工厂将被创建测试/工厂目录不是autowired / autoconfigure标准Symfony Flex应用程序,您必须手动注册这些服务。ob娱乐下载

匿名的工厂

铸造可用于创建实体工厂,你没有模型工厂:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
使用应用程序\实体\帖子;使用Zenstruck\铸造\AnonymousFactory;使用函数Zenstruck\铸造\工厂;使用函数Zenstruck\铸造\创建;使用函数Zenstruck\铸造\create_many;美元工厂= AnonymousFactory::(文章::类);美元工厂=工厂(职位::类);/ /选择/ /已经像ModelFactory相同的API美元工厂- >创建([“字段”= >“价值”]);美元工厂- >许多(5)- >创建([“字段”= >“价值”]);美元工厂- >instantiateWith (函数(){});美元工厂- >beforeInstantiate (函数(){});美元工厂- >afterInstantiate (函数(){});美元工厂- >afterPersist (函数(){});/ /找到一个持久化对象给定属性,如果没有找到,创建的属性美元工厂- >findOrCreate ([“标题”= >“我的名字”]);美元工厂- >第();/ /获得第一个对象(假设一个自动递增的“id”列)美元工厂- >第一次(“createdAt”);/ /假设“createdAt”是一个datetime列,这将返回最新的对象美元工厂- >最后();/ /得到最后一个对象(假设一个自动递增" id "列)美元工厂- >最后一个(“createdAt”);/ /假设“createdAt”是一个datetime列,这将返回古老的对象美元工厂- >截断();/ /清空数据库表中美元工厂- >count ();/ /保存后的数量美元工厂- >所有();/ /发布代理[][]|坚持邮政的美元工厂- >findBy ([“作者”= >“凯文”]);/ /发布代理[][]|匹配滤波器美元工厂- >找到(5);/ /发布| 5代理的id美元工厂- >找到([“标题”= >“我的第一个帖子”]);/ /发布|代理匹配滤波器/ /得到一个随机的对象,一直坚持美元工厂- >随机();/ /返回帖子|代理美元工厂- >随机([“作者”= >“凯文”]);/ /通过过滤器的属性/ /或自动保存一个新的随机对象如果没有存在美元工厂- >randomOrCreate ();美元工厂- >randomOrCreate ([“作者”= >“凯文”]);/ /过滤或创造与传递的属性/ /获得一个随机设置的对象持久化美元工厂- >randomSet (4);/ /数组包含4“后|代理”对象美元工厂- >randomSet (4,(“作者”= >“凯文”]);/ /通过过滤器的属性/ /随机持久化对象的范围美元工厂- >randomRange (0,5);/ /数组包含0 - 5“后|代理”对象美元工厂- >randomRange (0,5,(“作者”= >“凯文”]);/ /通过过滤器的属性/ /存储库代理包装PostRepository(见库代理后面的一节)美元工厂- >存储库();/ /便利的函数美元实体=创建(职位::类,“字段”= >“价值”]);美元实体= create_many(职位::类,5,(“字段”= >“价值”]);

延迟冲洗

在创建/持久化许多工厂,它可以提高性能来实例化都没有保存到数据库,然后冲洗。要做到这一点,包装的操作工厂::delayFlush ()回调函数:

1 2 3 4 5 6
使用Zenstruck\铸造\工厂;工厂::delayFlush (函数(){CategoryFactory::createMany (One hundred.);/ /实例化/坚持但不刷新TagFactory::createMany (200年);/ /实例化/坚持但不刷新});/ /单冲

没有坚持

工厂还可以创建对象,而不坚持。这可以用于单元测试,你只是想测试实际对象或创建对象的行为不是实体。创建时,他们仍裹着代理选择保存。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21日22日23日24日25日26日
使用应用程序\工厂\PostFactory;使用应用程序\实体\帖子;使用Zenstruck\铸造\AnonymousFactory;使用函数Zenstruck\铸造\实例化;使用函数Zenstruck\铸造\instantiate_many;美元帖子= PostFactory::()- >withoutPersisting ()- >create ();/ /返回帖子|代理美元帖子- >setTitle (“别的东西”);/ /做一些与对象美元帖子- >save ();/ /保存Post (save()方法代理)美元帖子= PostFactory::()- >withoutPersisting ()- >create ()- >对象();/ /实际的对象美元的帖子= PostFactory::()- >withoutPersisting ()- >许多(5)- >create ();/ /返回邮政代理[][]|/ /匿名工厂:美元工厂=AnonymousFactory (Post::类);美元实体=美元工厂- >withoutPersisting ()- >创建([“字段”= >“价值”]);/ /返回帖子|代理美元实体=美元工厂- >withoutPersisting ()- >创建([“字段”= >“价值”])- >对象();/ /实际的对象美元实体=美元工厂- >withoutPersisting ()- >许多(5)- >创建([“字段”= >“价值”]);/ /返回邮政代理[][]|/ /便利的函数美元实体=实例化(职位::类,“字段”= >“价值”]);美元实体= instantiate_many(职位::类,5,(“字段”= >“价值”]);

如果你想让你的模型工厂没有保存在默认情况下,覆盖它初始化()方法添加这种行为:

1 2 3 4 5 6
受保护的函数初始化():自我{返回美元- >withoutPersisting ();}

现在,使用这个工厂创建对象后,您必须调用- >保存()将它们持久化到数据库中。

提示

如果你想禁用默认坚持为所有您的模型工厂:

  1. 创建一个抽象的模型工厂扩展Zenstruck \铸造\ ModelFactory
  2. 覆盖初始化()方法如上所示。
  3. 有你所有的模型工厂扩展。

使用DoctrineFixturesBundle

铸造的盒子DoctrineFixturesBundle。你可以简单地使用你的工厂和故事在你的设备文件:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35
/ / src / DataFixtures / AppFixtures.php名称空间应用程序\DataFixtures;使用应用程序\工厂\CategoryFactory;使用应用程序\工厂\CommentFactory;使用应用程序\工厂\PostFactory;使用应用程序\工厂\TagFactory;使用学说\\FixturesBundle\夹具;使用学说\持久性\ObjectManager;AppFixtures扩展夹具{公共函数负载(ObjectManager美元经理){/ /创建10个类别CategoryFactory::createMany (10);/ /创建20个标记TagFactory::createMany (20.);/ /创建50个邮政的PostFactory::createMany (50,函数(){返回(/ /每个帖子将使用一个随机类别(从上面创建的选择)“类别”= > CategoryFactory::随机(),/ / 0和6之间的每个帖子都有标记的(从上面创建的选择)“标签”= > TagFactory::randomRange (0,6),/ /每个帖子都有0和10之间创建新的评论“评论”= > CommentFactory::()- >许多(0,10),);});}}

运行原则:设备:负载正常种子数据库。

使用在你的测试

传统上,数据设备之外的一个或多个文件中定义您的测试。当你使用这些设备,编写测试夹具是一种黑盒。没有明确的设备之间的连接和你测试。

铸造允许每个测试完全遵循AAA(“安排”、“行为”、“维护”)测试模式。您创建您的设备使用“工厂”在每个测试的开始。你只创建适用于测试的装置。此外,这些设备只有创建测试所需的属性,属性不适用充满了随机数据。创建的设备对象都封装在一个“代理”,帮助与前后断言。

让我们来看一个例子:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32
公共函数test_can_post_a_comment():无效{/ / 1。“安排”美元帖子= PostFactory::()/ /新职位工厂- >(出版)/ /使《华盛顿邮报》在“发布”状态- >创建([/ /实例化对象和坚持“鼻涕虫”= >“发布”/ /这个测试只需要“鼻涕虫”领域——所有其他字段是随机数据]);/ / 1。“Pre-Assertions”美元- >assertCount (0,美元帖子- >getComments ());/ / 2。“行动”静态::ensureKernelShutdown ();/ /创建工厂靴子内核;在创建客户机之前关闭美元客户端=静态::createClient ();美元客户端- >请求(“得到”,“/文章/发布”);/ /注意安排的蛞蝓的一步美元客户端- >submitForm (“添加”,(“评论[名字]”= >“约翰。”,的评论(身体)= >“我的评论”]);/ / 3。“维护”自我::assertResponseRedirects (“/文章/发布”);美元- >assertCount (1,美元帖子- >refresh ()- >getComments ());/ /刷新$发布从数据库和电话- > getComments ()CommentFactory::assert ()- >存在([/ /学说库断言“名字”= >“约翰。”,“身体”= >“我的评论”]);}

使铸造TestCase

添加工厂特征为测试使用工厂:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
使用应用程序\工厂\PostFactory;使用Zenstruck\铸造\测试\工厂;使用ob娱乐下载\\FrameworkBundle\测试\WebTestCase;MyTest扩展WebTestCase{使用工厂;公共函数test_1():无效{美元帖子= PostFactory::createOne ();/ /……}}

数据库重启

这个图书馆要求每个测试之前数据库被重置。打包的ResetDatabase特征为你处理这个。

1 2 3 4 5 6 7 8 9 10
使用Zenstruck\铸造\测试\工厂;使用Zenstruck\铸造\测试\ResetDatabase;使用ob娱乐下载\\FrameworkBundle\测试\WebTestCase;MyTest扩展WebTestCase{使用ResetDatabase,工厂;/ /……}

第一个测试使用ResetDatabase特征,它滴(如果存在)并创建测试数据库。然后,默认情况下,在每个测试之前,重置模式使用原则:模式:下降/原则:模式:创建

或者,您可以运行您的迁移而不是通过修改reset_mode选择配置文件。当使用这个模式在每个测试之前,被删除/创建数据库和迁移(通过运行原则:迁移:迁移)。这种模式可以使您的测试套件中缓慢(特别是如果你有大量的迁移)。强烈建议使用DamaDoctrineTestBundle提高速度。启用此包时,数据库被删除/创建和套件只迁移一次。

提示

使用工厂创建一个基本TestCase测试避免增加每个TestCase的特征。

提示

如果您的测试不坚持他们创造的对象,这些测试不需要特征。

默认情况下,ResetDatabase重置默认配置连接数据库和对象管理器默认配置的模式。定制的连接和对象管理器复位(或重置多个连接/经理),使用包的配置:

  • YAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#配置/包/ zenstruck_foundry.yamlwhen@dev:#包配置部分中看到的分享这个测试环境zenstruck_foundry:database_resetter:orm:连接:- - - - - -orm_connection_1- - - - - -orm_connection_2object_managers:- - - - - -orm_object_manager_1- - - - - -orm_object_manager_2reset_mode:模式odm:object_managers:- - - - - -odm_object_manager_1- - - - - -odm_object_manager_2

对象代理

创建的对象工厂被包装在一个特殊的代理对象。这些对象让你学说实体活动记录就像行为:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
使用应用程序\工厂\PostFactory;美元帖子= PostFactory::createOne ([“标题”= >“我的名字”]);/ / Zenstruck \铸造\代理的实例/ /得到包装对象美元realPost=美元帖子- >对象();/ /文章的实例/ /调用任何Post方法美元帖子- >getTitle ();/ /“我的标题”/ /设置属性并保存到数据库中美元帖子- >setTitle (“新标题”);美元帖子- >save ();/ /从数据库刷新美元帖子- >refresh ();/ /从数据库中删除美元帖子- >remove ();美元帖子- >存储库();/ /存储库代理包装PostRepository(见库代理后面的一节)

力设置

对象代理有辅助方法来访问非公开属性的对象他们包装:

1 2 3 4 5
/ /设置私人/保护属性美元帖子- >forceSet (“createdAt”,\ DateTime ());/ /得到私人/保护属性美元帖子- >forceGet (“createdAt”);

自动刷新

对象可以选择启用代理自动刷新这消除了需要调用- > refresh ()在底层对象上调用方法。当启用自动刷新时,最先调用代理对象刷新包对象从数据库中。

1 2 3 4 5 6 7 8 9 10
使用应用程序\工厂\PostFactory;美元帖子= PostFactory::([“标题”= >“标题”])- >create ()- >enableAutoRefresh ();/ /……逻辑改变了文章标题美元“新标题”(如功能测试)美元帖子- >getTitle ();/ /“新标题”(相当于$ post - > refresh () - > getTitle ())

没有启用自动刷新,上面的调用$ post - > getTitle ()将返回“原始标题”。

请注意

情况需要注意当使用自动刷新,刷新对象的所有方法。如果改变对象的状态(或多个force-sets)通过多种方法,将抛出一个“未保存的更改”异常:

1 2 3 4 5 6 7 8 9
使用应用程序\工厂\PostFactory;美元帖子= PostFactory::([“标题”= >“标题”,“身体”= >“原来的身体”])- >create ()- >enableAutoRefresh ();美元帖子- >setTitle (“新标题”);美元帖子- >setBody (“新的身体”);/ /异常抛出,因为“未保存的更改”从后美元以上

要克服这一点,您需要首先禁用自动刷新,然后重新启用后/保存更改:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31
使用应用程序\实体\帖子;使用应用程序\工厂\PostFactory;美元帖子= PostFactory::([“标题”= >“标题”,“身体”= >“原来的身体”])- >create ()- >enableAutoRefresh ();美元帖子- >disableAutoRefresh ();美元帖子- >setTitle (“新标题”);/ /或使用- > forceSet(“标题”、“新标题”)美元帖子- >setBody (“新的身体”);/ /或使用- > forceSet(“身体”、“新机构”)美元帖子- >enableAutoRefresh ();美元帖子- >save ();美元帖子- >getBody ();/ /“新身体”美元帖子- >getTitle ();/ /“新标题”/ /另外,使用- > withoutAutoRefresh()辅助第一禁用自动刷新,之后还可以重新开启/ /执行回调。美元帖子- >withoutAutoRefresh (函数(文章美元帖子){/ /可以通过邮政或代理回调美元帖子- >setTitle (“新标题”);美元帖子- >setBody (“新的身体”);});美元帖子- >save ();/ /如果force-setting属性,您可以使用- > forceSetAll()辅助:美元帖子- >forceSetAll ([“标题”= >“新标题”,“身体”= >“新的身体”]);美元帖子- >save ();

请注意

你可以启用/禁用自动刷新全球每个代理auto-refreshable默认情况下。当启用时,你将不得不选择退出自动刷新。

  • YAML
1 2 3 4
#配置/包/ zenstruck_foundry.yamlwhen@dev:#包配置部分中看到的分享这个测试环境zenstruck_foundry:auto_refresh_proxies:真正的/错误

库代理

这个库提供了一个库代理包装对象存储库来提供有用的断言和方法:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36
使用应用程序\实体\帖子;使用应用程序\工厂\PostFactory;使用函数Zenstruck\铸造\存储库;/ /封装PostRepository RepositoryProxy的实例美元存储库= PostFactory::存储库();/ /代理库替代上面你没有工厂创建的模型美元存储库=库(职位::类);/ /有帮助的方法——所有返回的对象(s)是代理美元存储库- >内部();/ /真正的“包装”库美元存储库- >count ();/ /数据库表的行数计数(美元存储库);/ /以上相当于(RepositoryProxy实现\可数)美元存储库- >第();/ /获得第一个对象(假设一个自动递增的“id”列)美元存储库- >第一次(“createdAt”);/ /假设“createdAt”是一个datetime列,这将返回最新的对象美元存储库- >最后();/ /得到最后一个对象(假设一个自动递增" id "列)美元存储库- >最后一个(“createdAt”);/ /假设“createdAt”是一个datetime列,这将返回古老的对象美元存储库- >截断();/ /删除数据库表中的所有行美元存储库- >随机();/ /得到一个随机的对象美元存储库- >随机([“作者”= >“凯文”]);/ /获得一个随机的对象通过过滤的标准美元存储库- >randomSet (5);/ /得到5个随机对象美元存储库- >randomSet (5,(“作者”= >“凯文”]);/ /得到5个随机筛选的对象传递标准美元存储库- >randomRange (0,5);/ /得到0 - 5随机对象美元存储库- >randomRange (0,5,(“作者”= >“凯文”]);/ /通过0 - 5随机筛选的对象标准/ / ObjectRepository——所有的实例返回的对象(s)是代理美元存储库- >找到(1);/ /代理| |空美元存储库- >找到([“标题”= >“我的名字”]);/ /代理| |空美元存储库- >findOneBy ([“标题”= >“我的名字”]);/ /代理| |空美元存储库- >findAll ();/ /代理[]|文章[]iterator_to_array (美元存储库);/ /以上相当于(RepositoryProxy实现\ IteratorAggregate)美元存储库- >findBy ([“标题”= >“我的名字”]);/ /代理[]|文章[]/ /可以调用底层存储库上的方法返回的对象(s)是代理美元存储库- >findOneByTitle (“我的名字”);/ /代理| |空

断言

对象代理和你ModelFactory有用PHPUnit)断言:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
使用应用程序\工厂\PostFactory;美元帖子= PostFactory::createOne ();美元帖子- >assertPersisted ();美元帖子- >assertNotPersisted ();PostFactory::assert ()- >();PostFactory::assert ()- >计数(3);PostFactory::assert ()- >countGreaterThan (3);PostFactory::assert ()- >countGreaterThanOrEqual (3);PostFactory::assert ()- >countLessThan (3);PostFactory::assert ()- >countLessThanOrEqual (3);PostFactory::assert ()- >存在([“标题”= >“我的名字”]);PostFactory::assert ()- >notExists ([“标题”= >“我的名字”]);

全局状态

如果你有一个初始数据库状态你想对所有的测试,你可以在包的配置设置。接受的价值观是:故事作为服务,“全球”的故事和调用服务。

  • YAML
1 2 3 4 5 6 7 8
#配置/包/ zenstruck_foundry.yamlwhen@test:#包配置部分中看到的分享这个测试环境zenstruck_foundry:global_state:- - - - - -应用\ \ StoryThatIsAService故事- - - - - -应用\ \ GlobalStory故事- - - - - -invokable.service#服务::调用()- - - - - -

请注意

你仍然可以访问故事的状态全球国家的故事在测试中,他们仍然只加载一次。

请注意

ResetDatabase特征时需要使用全局状态。

PHPUnit)数据提供者

可以使用工厂PHPUnit)数据提供者:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
使用应用程序\工厂\PostFactory;/ * * *@dataProviderpostDataProvider * /公共函数test_post_via_data_provider(PostFactory美元工厂):无效{美元帖子=美元工厂- >create ();/ /……}公共静态函数postDataProvider():iterable{收益率[PostFactory::());收益率[PostFactory::()- >发表()];}

请注意

确保您的数据提供者只返回的实例ModelFactory你不要试图调用- > create ()在他们身上。数据提供商计算铸造启动之前在phpunit)过程的早期。

请注意

出于同样的原因,如上所述,它是不可能的工厂为服务使用所需的构造函数参数(容器还没有可用的)。

提示

ModelFactory::新()- > ()ModelFactory::新()- >序列()返回一个特殊的FactoryCollection对象可用于生成数据提供者:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
使用应用程序\工厂\PostFactory;/ * * *@dataProviderpostDataProvider * /公共函数test_post_via_data_provider(PostFactory美元工厂):无效{美元工厂- >create ();/ /……}公共静态函数postDataProvider():iterable{收益率从PostFactory::()- >序列([[“标题”= >“foo”]、[“标题”= >“酒吧”),)- >asDataProvider ();}

FactoryCollection也可以直接传递给测试用例为了有几个可用的对象在同一测试:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31
使用应用程序\工厂\PostFactory;/ * * *@dataProviderpostDataProvider * /公共函数test_post_via_data_provider(FactoryCollection美元factoryCollection):无效{美元factoryCollection- >create ();/ /……}公共静态函数postDataProvider():iterable{/ / 3职位将为第一个创建测试用例收益率PostFactory::()- >序列([[“标题”= >“foo 1”]、[“标题”= >“酒吧1 ']、[“标题”= >“巴兹1”)));/ / 2的帖子将被创建为第二个测试用例收益率PostFactory::()- >序列([[“标题”= >“foo 2”]、[“标题”= >《酒吧2》)));}

性能

以下是可能的选择来提高您的测试套件的速度。

DAMADoctrineTestBundle

这个库无缝集成DAMADoctrineTestBundle包装每个测试在一个事务中,可以显著降低测试时间。这个库的测试套件运行启用了这个包的快5倍。

按照文档安装。欧宝官网下载app铸造的ResetDatabase特征检测当使用包,并相应地调整。数据库仍然是重置在运行测试套件,但之前的模式不是重置之前每个测试(仅第一次)。

请注意

如果使用全局状态,它是持久化到数据库(而不是在一个事务)在你运行测试套件。这可能会进一步提高测试速度,如果你有一个复杂的全局状态。

谨慎

使用全局状态创建两个ORM和ODM工厂不支持使用DAMADoctrineTestBundle时。

杂项

  1. 运行测试时禁用调试模式。在你的.env.test文件,你可以设置APP_DEBUG = 0你的测试运行没有调试模式。这可以大大加快您的测试。你需要确保你是在运行测试套件之前清除缓存。这是你的最好的地方测试/ bootstrap.php:

    1 2 3 4 5 6
    / /测试/ bootstrap.php/ /……如果(= = =(保龄球)美元_SERVER(“APP_DEBUG”){/ /确保新鲜的缓存(ob娱乐下载Symfony \文件系统组件\ \文件系统())- >remove (__DIR__“/ . . / var /缓存/测试”);}
  2. 减少密码编码器工作因素。如果你有很多的测试和编码的密码,这将导致这些测试是不必要的缓慢。你可以提高速度降低工作因素你的编码器:

    1 2 3 4 5 6 7 8 9
    #配置/包/测试/ security.yaml编码器:#使用您的用户类的名字应用实体\ \用户:#这应该是相同的值作为配置/包/ security.yaml算法:汽车成本:4# bcrypt最低的值time_cost:3#为氩最低的价值memory_cost:10#为氩最低的价值
  3. Pre-encode与已知值通过用户密码bin /控制台安全:encode-password和设置这个ModelFactory: getDefaults ()。添加的已知值常量在你的工厂:

    1 2 3 4 5 6 7 8 9 10 11 12
    UserFactory扩展ModelFactory{公共常量DEFAULT_PASSWORD =“1234”;/ /密码用于创建以下pre-encoded版本受保护的函数getDefaults():数组{返回(/ /……“密码”= >“argon2id v = 19美元= 65536美元,t = 4, p = 1 pLFF3D2gnvDmxMuuqH4BrA 3美元vkfv0cw + 6 eanspq9btvayc + jCOqrmWRstInB2fRPeQ ',);}}

    现在,在您的测试中,当您需要访问用户创建的未编码的密码UserFactory,使用UserFactory: DEFAULT_PASSWORD

没有测试

铸造可用于标准PHPUnit)单元测试(TestCase扩展PHPUnit) \ \ TestCase的框架而不是ob娱乐下载\包\ FrameworkBundle\测试\ KernelTestCase)。这些测试仍然需要使用工厂特征引导铸造但不会有原则。工厂中创建这些测试将不会坚持(要求- > withoutPersisting ()没有必要)。因为在这些测试包不可用,任何包配置你有不会捡起。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
使用应用程序\工厂\PostFactory;使用PHPUnit)\框架\TestCase;使用Zenstruck\铸造\测试\工厂;MyUnitTest扩展TestCase{使用工厂;公共函数some_test():无效{美元帖子= PostFactory::createOne ();/ /美元后不是持久化到数据库中}}

您将需要手动配置铸造。不幸的是,这可能意味着在这里复制你的包配置。

1 2 3 4 5 6 7 8 9 10
/ /测试/ bootstrap.php/ /……Zenstruck \铸造\ \ TestState测试::配置(instantiator:(Zenstruck \铸造\ Instantiator ())- >withoutConstructor ()- >allowExtraAttributes ()- >alwaysForceProperties(),骗子:骗子\工厂::创建(“fr_FR”));

请注意

工厂为服务故事作为服务使用所需的构造函数参数没有可用的内核测试。容器是不可以解决他们的依赖性。最简单的方法是使测试的实例ob娱乐下载\包\ FrameworkBundle\测试\ KernelTestCase容器是可用的。

故事

如果你发现你的测试的故事是有用的安排步骤越来越复杂(加载大量的设备)或复制逻辑测试和/或您的开发装置之间。他们是用于提取一个特定的数据库状态成一个故事。故事可以加载在你的设备在您的测试,他们也可以依赖于其他的故事。

使用制造商命令创建一个故事:

1
美元bin /控制台:故事

请注意

创建PostStory.phpsrc /故事,添加——测试国旗在测试/故事

修改构建这个故事的方法来设置状态:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31
/ / src /故事/ PostStory.php名称空间应用程序\故事;使用应用程序\工厂\CategoryFactory;使用应用程序\工厂\PostFactory;使用应用程序\工厂\TagFactory;使用Zenstruck\铸造\故事;最后PostStory扩展故事{公共函数构建():无效{/ /创建10个类别CategoryFactory::createMany (10);/ /创建20个标记TagFactory::createMany (20.);/ /创建50个邮政的PostFactory::createMany (50,函数(){返回(/ /每个帖子将使用一个随机类别(上面创建)“类别”= > CategoryFactory::随机(),/ / 0和6之间的每个帖子将标记的(上面创建)“标签”= > TagFactory::randomRange (0,6),);});}}

使用新的故事在你的测试中,开发装备,甚至其他的故事:

1 2 3
PostStory::load ();/ /加载PostStory中定义的状态::建立()PostStory::load ();/ /什么也不做——已经加载

请注意

每个测试对象保存在故事后被清除(除非它是一个全球国家的故事)。

故事作为服务

如果你的故事需要依赖项,您可以定义为一个服务:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21日22日23日24日25
/ / src /故事/ PostStory.php名称空间应用程序\故事;使用应用程序\工厂\PostFactory;使用应用程序\服务\ServiceA;使用应用程序\服务\ServiceB;使用Zenstruck\铸造\故事;最后PostStory扩展故事{私人美元serviceA;私人美元serviceB;公共函数__construct(ServiceA美元serviceA,ServiceB美元serviceB){美元- >serviceA =美元serviceA;美元- >serviceB =美元serviceB;}公共函数构建():无效{/ /可以使用$ this - > serviceA, $ this - > serviceB帮助建立这故事}}

如果使用一个标准的Symfony Fleob娱乐下载x应用程序,这将是autowired / autoconfigure。如果没有,注册服务和标签foundry.story

请注意

作为服务提供的包需要故事。

故事的状态

的另一个特点故事是他们的能力还记得他们创建的对象引用后:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/ / src /故事/ CategoryStory.php名称空间应用程序\故事;使用应用程序\工厂\CategoryFactory;使用Zenstruck\铸造\故事;最后CategoryStory扩展故事{公共函数构建():无效{美元- >addState (“php”,CategoryFactory::createOne ([“名字”= >“php”)));/ /创建工厂添加时的状态美元- >addState (sob娱乐下载ymfony的,CategoryFactory::([“名字”= >sob娱乐下载ymfony的)));}}

后,您可以访问故事的状态在创建其他设备:

1 2 3 4
PostFactory::createOne ([“类别”= > CategoryStory::get (“php”)));/ /或者使用魔法的方法(功能与上图)PostFactory::createOne ([“类别”= > CategoryStory::php ()));

请注意

故事状态是每个测试(除非它是一个后清除全球国家的故事)。

故事池

故事可以存储(状态)的对象:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21日22日23日24
/ / src /故事/ ProvinceStory.php名称空间应用程序\故事;使用应用程序\工厂\ProvinceFactory;使用Zenstruck\铸造\故事;最后ProvinceStory扩展故事{公共函数构建():无效{/ /添加收藏“池”美元- >addToPool (“是”,ProvinceFactory::createMany (5,(“国家”= >“是”)));/ /相当于上面美元- >addToPool (“是”,ProvinceFactory::([“国家”= >“是”])- >许多(5));/ /添加单一对象池美元- >addToPool (“是”,ProvinceFactory::createOne ([“国家”= >“是”)));/ /添加单一对象单一池和提供“状态”美元- >addState (“1”,ProvinceFactory::createOne ([“国家”= >“是”]),“是”);}}

对象可以从池中获取您的测试、设备或其他故事:

1 2 3 4
ProvinceStory::getRandom (“是”);/ /随机省|代理从“是”池ProvinceStory::getRandomSet (“是”,3);/ / 3 |随机省代理的从“是”池ProvinceStory::getRandomRange (“是”,1,4);/ / | 1和4之间随机省代理的从“是”池ProvinceStory::getPool (“是”);/ /省|代理所有的从“是”池

包配置

由于包中使用dev测试环境中,您可以配置为每个环境相匹配。最简单的方法是使用YAML锚when@dev/when@test。这样,只有一个地方设置配置。

  • YAML
1 2 3 4 5 6 7
#配置/包/ zenstruck_foundry.yamlwhen@dev:devzenstruck_foundry:#……把所有的配置when@test:*开发#“副本”上面的配置

全部默认包配置

  • YAML
  • PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
zenstruck_foundry:#是否自动刷新默认代理(https://github.com/zenstruck/foundry自动刷新)auto_refresh_proxies:真正的#配置骗子使用你的工厂。骗子:#修改默认摊贩的地区。地区:#例子:fr_FR#随机数生成器的种子生产每运行相同的假值种子:#例子:1234#定制伪造者服务。服务:#例子:my_faker#配置默认instantiator使用的工厂。instantiator:#是否调用在实例化一个对象的构造函数。without_constructor:#是否允许额外的属性。allow_extra_attributes:#是否跳过设置对象属性setter和力量直接(公共/私人/保护)。always_force_properties:#定制instantiator服务。服务:#例子:my_instantiator#配置数据库重置机制database_resetter:#配置与ORMorm:#连接重置。如果为空,默认连接使用。连接:[]#重置对象管理器。如果为空,默认使用经理。object_managers:[]#是否使用原则:模式:更新或迁移时重置模式。reset_mode:模式#“模式”或“迁移”#配置ODModm:#重置对象管理器。如果为空,默认使用经理。object_managers:[]#添加全局状态。global_state:[]
这项工作,包括代码示例,许可下Creative Commons冲锋队3.0许可证。