Java 是否存在像 Factory Girl 这样的框架?

发布于 2024-07-23 17:03:40 字数 1542 浏览 8 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

蓝颜夕 2024-07-30 17:03:40

我还寻找了 Factory Girl 的 Java 版本,但从未找到类似的东西。 相反,我从头开始创建了一个解决方案。 用于用 Java 生成模型的工厂:Model Citizen

受 Factory Girl 的启发,它使用字段注释来设置模型的默认值,一个简单的示例来自 wiki

@Blueprint(Car.class)
public class CarBlueprint {

    @Default
    String make = "car make";

    @Default
    String manufacturer = "car manufacturer";

    @Default
    Integer mileage = 100;

    @Default
    Map status = new HashMap();
}

这将是汽车模型的蓝图。 这已注册到 ModelFactory 中,然后可以按如下方式创建新实例:

ModelFactory modelFactory = new ModelFactory();
modelFactory.registerBlueprint( CarBlueprint.class );
Car car = modelFactory.createModel(Car.class);

您可以通过传入 Car 实例而不是 Class 并根据需要设置值来覆盖 Car 模型的值:

Car car = new Car();
car.setMake( "mustang" );
car = modelFactory.createModel( car );

wiki 有更复杂的示例(例如使用 @Mapped)以及更多附加功能的详细信息。

I also looked for a Java equivalent of Factory Girl, but never found anything like it. Instead, I created a solution from scratch. A factory for generating models in Java: Model Citizen.

Inspired by Factory Girl, it uses field annotations to set defaults for a Model, a simple example from the wiki:

@Blueprint(Car.class)
public class CarBlueprint {

    @Default
    String make = "car make";

    @Default
    String manufacturer = "car manufacturer";

    @Default
    Integer mileage = 100;

    @Default
    Map status = new HashMap();
}

This would be the Blueprint for the Car model. This is registered into the ModelFactory, than new instances can be created as follows:

ModelFactory modelFactory = new ModelFactory();
modelFactory.registerBlueprint( CarBlueprint.class );
Car car = modelFactory.createModel(Car.class);

You can override the values of the Car model by passing in an instance of Car instead of the Class and setting values as needed:

Car car = new Car();
car.setMake( "mustang" );
car = modelFactory.createModel( car );

The wiki has more complex examples (such as using @Mapped) and details for a few more bells and whistles.

尾戒 2024-07-30 17:03:40

一个可能执行此操作的库是 Usurper

然而,如果您想指定正在创建的对象的属性,那么 Java 的静态类型会使框架变得毫无意义。 您必须将属性名称指定为字符串,以便框架可以使用反射或 Java Bean 自省来查找属性访问器。 这将使重构变得更加困难。

只需新建对象并调用它们的方法就简单得多。 如果您想在测试中避免大量样板代码,测试数据生成器 模式可以提供帮助。

One possible library for doing this is Usurper.

However, if you want to specify properties of the objects you are creating, then Java's static typing makes a framework pointless. You'd have to specify the property names as strings so that the framework could look up property accessors using reflection or Java Bean introspection. That would make refactoring much more difficult.

It's much simpler to just new up the objects and call their methods. If you want to avoid lots of boilerplate code in tests, the Test Data Builder pattern can help.

锦欢 2024-07-30 17:03:40
  1. 我知道这并不适合所有人,但是您可以针对 Java 代码编写 Ruby 测试代码。 (JTestR)
  2. 在 Java 中执行此操作的首选方法是使用 测试数据生成器 模式。 我认为这种方法并不能真正保证引入框架或外部依赖的复杂性。 我只是不明白如何使用框架指定更少的内容并从中获得更多内容...... Builder 语法本质上等同于 FactoryGirl 语法。 (有人可以随意说服我!)
  1. I understand this isn't for everybody, but you could write Ruby test code against your Java code. (JTestR)
  2. The preferred way of doing this in Java is using the Test Data Builder pattern. I would argue that this approach doesn't really warrant introducing the complexity of a framework or external dependency. I just don't see how you could specify much less using a framework and get anything more out of it... the Builder syntax is essentially equivalent to your FactoryGirl syntax. (Someone feel free to convince me otherwise!)
故事灯 2024-07-30 17:03:40

我知道这并不完全是您正在寻找的...

过去我编写了一些使用反射来填充 beans 值的代码。 基本思想是找到所有设置器并使用虚拟值调用每个设置器。 我的版本将所有字符串设置为将使用“name”调用的字段 setName 的名称,然后将所有整数设置为 1,将布尔值设置为 true 等。

然后我将其与类似于对象母体和测试数据生成器的模式结合使用。

它为测试数据提供了良好的开端,任何需要特定值的字段都可以作为测试的一部分明确设置。

希望这可以帮助。

I know this isn't exactly what you are looking for...

I the past I've written some code that using reflection to populate a beans values. The basic idea is to find all the setters and call each with a dummy value. My version set all Strings as the name of the field setName would be called with "name", then set all ints as 1, booleans to true etc.

I then used this in conjuction with the patterns similar to Object mother and Test Data Builder.

It provided a good start for test data and any fields that required specific values could be set explicitly as part of the test.

Hope this helps.

甲如呢乙后呢 2024-07-30 17:03:40

我带着同样的问题来到这里,需要数据生成工具来进行集成测试。 我决定接受 Groovy 的挑战,它是我选择的测试语言,因为它的紧凑性和 电源断言

我刚刚写了一个小助手 https://gist.github.com/pgaertig/9502960称为 FactoryGrill ;)它允许您编写如下所示的数据脚本。

insert('MyTable', ID: 1, CREATED_AT: new Date(), NAME: 'Example text')

上面相当于:

INSERT INTO MyTable(ID, CREATED_AT, NAME) VALUES (1, ..current date here.., 'Example text')

你可以用 Groovy 做更多的事情:

import org.apache.commons.lang3.RandomStringUtils;

for ( i in 0..9 ) {
     insert('USERS', CREATED_AT: new Date(), EMAIL: "test${i}@mydomain.com",
                     SALT: RandomStringUtils.randomAlphanumeric(32));
}

load(new File('usersettings.groovy').text)    //script nesting etc

它实际上不是工厂,因为工厂在 Groovy 中非常简单 地图构造函数展开

FactoryGirl 的参考资料和其他内容目前不可用,因为上述内容仅需要约 30LOC 才能实现。 但是,如果对我的解决方案感兴趣,我将在 Github 上添加一个专门的项目。

I arrived here with the same question and needed for data generation tool for my integration tests. I decided to accept the challenge with Groovy, which is my language of choice for tests because of its compactness and power assert.

I've just written a small helper https://gist.github.com/pgaertig/9502960 called FactoryGrill ;) which allows you to write data scripts like below.

insert('MyTable', ID: 1, CREATED_AT: new Date(), NAME: 'Example text')

above is equivalent to:

INSERT INTO MyTable(ID, CREATED_AT, NAME) VALUES (1, ..current date here.., 'Example text')

You can do more with Groovy:

import org.apache.commons.lang3.RandomStringUtils;

for ( i in 0..9 ) {
     insert('USERS', CREATED_AT: new Date(), EMAIL: "test${i}@mydomain.com",
                     SALT: RandomStringUtils.randomAlphanumeric(32));
}

load(new File('usersettings.groovy').text)    //script nesting etc

It is not factory really because factories are quite straight forward in Groovy with map constructor or expandos.

References and other stuff from FactoryGirl is not available currently because above is achieved only with ~30LOC. However if there is an interest in my solution I will add make a dedicated project on Github.

话少心凉 2024-07-30 17:03:40

如果您的模型对象很简单,则没有理由使用框架来创建它们,只需使用“new”运算符即可。
如果你有复杂的模型(复杂的关系),那么你可以使用 spring 将它们绑定在一起(即使在测试场景中你也可以使用 spring),

  • 但这只是针对数据对象,如果你正在谈论实例化正在做某事的对象,建议模拟/存根外部关系而不是使用真实实例。

If your model objects are simple, there is not reason to use a framework to create them, just simply use 'new' operator.
If you have complex model (complex relationships) then you can use spring to bind them together (even in test scenarios you can use spring)

  • but this is simply for data objects, if you are talking about instantiating objects that are doing something, its recommended to mock/stub the external relationships instead of using real instances.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文