Pregunta

I want to write tests for my data models that make sense and work

I've been playing trying to test models like a boss in Laravel (right now I'd say I'm struggling to hold down a position in middle management). I'm using Ardent for my data models. The article referenced above makes it look like Factory Muff is super awesome and would be really handy in facilitating the creation of mock objects.

However, as I dig deeper, I find that Factory Muff is very limited in the data it can provide. It's basically just random words and email addresses. Anything beyond that, it seems I have to write a static method into my data model to generate valid data for the mock object. That doesn't seem very useful, but I'm guessing I'm probably doing it wrong, with a complete misunderstanding of what Factory Muff is all about.

In the data model

Consider this data validation ruleset:

public static $rules = [
    'property' => 'required|address',
    'name'     => 'required|name',
    'email'    => 'required|email',
    'phone'    => 'required|phone',
    'dob'      => 'required|date',
];

Factory Muff seems to be completely ill-suited to generate any of this data beyond the name and email address, unless I want to write a static method that generates data formatted in the correct fashion. This is what I think I have to do with Factory Muff to be able to create a mock object without getting validation errors:

public static $factory = [
    'property' => 'call|makeStreetAddress',
    'name'     => 'string',
    'email'    => 'email',
    'phone'    => 'call|makePhone',
    'dob'      => 'date|makeDate',
];

public static function makeStreetAddress()
{
    $faker = \Faker\Factory::create();
    return $faker->streetAddress;
}

public static function makePhone()
{
    $faker = \Faker\Factory::create();
    return $faker->phoneNumber;
}

public static function makeDate()
{
    $faker = \Faker\Factory::create();
    return $faker->date;
}

This seems pretty verbose, particularly with 10 to 20 fields on a table. I also don't like calling \Faker\Factory::create() in every single static method call (I don't really have a concrete reason, I just don't like it; if you know of a workaround, or if my fear is unfounded, please let me know.)

In the database seeder

I've got database seeding scripts setup that use Faker to generate a bunch of garbage in the database for use in development and testing. It's super intuitive and easy-to-use. For example, this is the seeding script for the above data set.

$faker = \Faker\Factory::create();

$application = Application::create([
    'property' => $faker->streetAddress,
    'name'     => $faker->name,
    'email'    => $faker->email,
    'phone'    => $faker->phoneNumber,
    'dob'      => $faker->dateTimeBetween('-60 years', '-18 years'),
]);

The more I think about what it is I'm doing here, the more I feel like I'm being redundant.

Questions

  1. If I'm seeding the database with garbage data generated by Faker before running my tests, do I even need Factory Muff to create mock objects? Shouldn't I be able to adequately test the codebase using the seed data from the database? Why would I need to mock?
  2. Am I missing the whole point of Faker Muff? Does it have any advantages? It seems to me like little more than a random word generator.
  3. What am I doing wrong? I'm extremely interested in TDD, but it's so daunting. If you noticed any bad practices, or the lack of best practices in my code, please let me know.
¿Fue útil?

Solución

I think you are mixing up two different concepts here.

First, the purpose of the data that you create with Faker (in your case, database seeding) is to simulate real life scenarios in your application. For example, if you are developing a blogging platform, you can use it to have some blog posts with tags, user comments and author comments.

When it comes to testing, you can use this in your functional or acceptance tests. For example, if you want to test something like test tag page shows posts tagged with X tag or test user can only delete his own comments, then you could take advantage of Faker data to have some previous posts, tags and comments to work with.


On the other hand, FactoryMuff allows you to quickly create an instance of any given model. Consider the scenario when you are unit testing the validation method for your Post model, so you would have to:

// 1. create new Post
// 2. fill it with data
// 3. try to validate

Having your database seeded is not going to be useful here, since you are going to be creating a new model, and FactoryMuff will do steps 1 and 2 for you. Also, keep in mind that when you are unit testing, you want to do it in isolation, so you shouldn't need to touch your database at all. Instead, you could mock your database object and return fake models and its possible relationships (FactoryMuff to the rescue again).


Finally, I think that maybe you are not seeing the advantages of FactoryMuff functionality because your application may be still small, but you will and won't mind writing a few static methods as your codebase –and your tests– grows.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top