Does a framework like Factory Girl exist for Java? [closed]
Asked Answered
R

6

28

Factory Girl is a handy framework in rails for easily creating instances of models for testing.

From the Factory Girl home page:

factory_girl allows you to quickly define prototypes for each of your models and ask for instances with properties that are important to the test at hand.

An example (also from the home page):

Factory.sequence :email do |n|
    "somebody#{n}@example.com"
end

# Let's define a factory for the User model. The class name is guessed from the
# factory name.
Factory.define :user do |f|
    # These properties are set statically, and are evaluated when the factory is
    # defined.
    f.first_name 'John'
    f.last_name  'Doe'
    f.admin      false
    # This property is set "lazily." The block will be called whenever an
    # instance is generated, and the return value of the block is used as the
    # value for the attribute.
    f.email      { Factory.next(:email) }
end

if I need a user a can just call

test_user = Factory(:user, :admin => true)

which will yield a user with all the properties specified in the factory prototype, except for the admin property which I have specified explicitly. Also note that the email factory method will yield a different email each time it is called.

I'm thinking it should be pretty easy to implement something similar for Java, but I don't want to reinvent the wheel.

P.S: I know about both JMock and EasyMoc, however I am not talking about a mocking framework here.

Repulse answered 12/6, 2009 at 12:58 Comment(3)
Can you give us an example of FactoryGirl does, without us having to go and read about it somewhere else?Jasen
There was one for Python until those frameworker's rights unions started gettin in the way!Implacable
Beanmother github.com/keepcosmos/beanmother is what you want.Upperclassman
C
8

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.

Collocutor answered 14/6, 2009 at 18:52 Comment(3)
Well said - I'd accept this answer if it were my question. :)Leena
Make it easy is somehow similar, as it helps to implement Test Data Builders, which define default values for each property.Abundant
Usurper link is broken, project seems to be dead.Electioneer
H
22

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.

Hyponitrite answered 4/9, 2012 at 6:38 Comment(0)
C
8

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.

Collocutor answered 14/6, 2009 at 18:52 Comment(3)
Well said - I'd accept this answer if it were my question. :)Leena
Make it easy is somehow similar, as it helps to implement Test Data Builders, which define default values for each property.Abundant
Usurper link is broken, project seems to be dead.Electioneer
L
2
  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!)
Leena answered 13/6, 2009 at 18:18 Comment(0)
A
1

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.

Arabia answered 14/6, 2009 at 17:8 Comment(0)
L
1

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.

Lunch answered 12/3, 2014 at 8:50 Comment(0)
H
-3

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.
Horologe answered 12/6, 2009 at 13:9 Comment(4)
"If your model objects are simple" They're not :-) "you can use spring to bind them together" Can you eloborate a bit on that? Let's say I have a Movie model, Movie has a number of Streams, each Stream has a Host. Now I would like 25 movies for testing purposes. How does Spring help me? What if I need 25 movies in the database to test my finder mehods?Repulse
I wouldn't recommend trying to build these using the 'new' keyword for objects of any complexity. At the very least you would want to use the Object Mother pattern (essentially create static factory methods for commonly initialized objects) but ideally you'd use the Builder pattern because it provides you sane defaults and a mechanism to override properties on a granular level.Leena
I think you are mixing too many things in here. - For database code testing, you have DBUnit for example that helps you manage the database pre/post test. - for a unit test you will not need 25 movies, 2 ore 3 are enough to UNIT test the class. My opinion is ... try to simplify your tests, and you'll see that you don't need a framework to build the input for the test.Horologe
When you accumulate a lot of unit tests, and for simplicity sake they all new up their own objects. When one of those objects adds a parameter in the constructor somewhere now you have to go change 50 some objects to account for that. Or worse, the change occurs in a deeply nested domain object. This is why people recommend using Object Mothers or Test Data Builders (or Factory Girl if you're in Ruby) - so that your Unit Tests aren't too difficult to maintain. When they are, people stop writing them, or just commenting them out, which defeats the purpose.Leena

© 2022 - 2024 — McMap. All rights reserved.