Discussion about this post

User's avatar
Jacek Andrzejewski's avatar

When dependencies are just pure logic I use real ones.

When they do some effects like database queries I have parameters for A with potential results of BCD. Then only when B result is missing it is called.

This way I can kind of mock it, without using flaky mocking.

Example code

```

class SchedulePlanner {

public function plan(Datetime date, ?Employee[] employees = null, ?Shift[] = null) {

employees ??= self::getEmployees(date);

shifts ??= self::getShifts(date);

(...)

}

}

```

And then in test I can just pass the results I'd want.

```

planner = new SchedulePlanner(date);

//In real test customize employees and shifts

employees = EmployeeFactory::create(2);

shifts = ShiftFactory::create(2);

plan = planner->plan(date,employees, shifts);

```

If I were to describe it shortly then I'd say it's functional approach bolted onto OOP.

I don't know if it's very good, but for me it has worked so far.

Expand full comment
Jacek Andrzejewski's avatar

Another way to explain it: looking at last image you'll see that you test only the class accessible from outside the module.

So tests should only do things that production code would do.

Of course you can have tests for internal classes inaccessible from outside. But it's rather a function test or class test, not unit test. You could call it a logic test maybe.

Expand full comment
6 more comments...

No posts