Hi Guys.
I’m creating a new project, this time in Symfony, and an old question keeps poping up and I would like to hear your thoughts.
When creating tests, should I focus on:
- Testing the service container definition
- Unit testing the implementation of that service
- Both
- A mix
As an example, lets assume that I’m defined in the services.yml
the following:
foobar_service:
class: Foo\Bar
arguments: [@"dep1", @"dep2"]
and it’s implementation is:
namespace Foo;
public class Bar implements IBar {
/** private dependencies accessors */
public __constructor($dep1, $dep2) { ... }
//IBar implementation
public doSomething($arg1) { return $arg1 * 2; }
}
The tests for scenario 1, where I want to test the provided service, could be:
public function testDoSomethingSuccess() {
$kernel = static::createKernel();
$kernel->boot();
$foobar_service = $kernel->getContainer()->get('foobar_service');
$this->assertEquals(2, $foobar_service->doSomething(1));
}
The tests for scenario 2, where I want to test the implementation. could be:
public function testDoSomethingSuccess() {
$stubDep1 = $this->mockDep1();
$stubDep2 = $this->mockDep2();
$foobar = new \Foo\Bar($stubDep1, $stubDep2);
$this->assertEquals(2, $foobar->doSomething(1));
}
The first one I consider a functional test and “assures” that the interface is tested whatever the implementation would be, and I could switch implementation and “assure” that it works. But it’s a pain to test as it doesn’t allow me to control the dependencies, the input data is harder to control, and I can’t assure what I can’t see (the interactions with dep1
and dep2
) But, as a user of service foobar_service
this is what I want to rely on.
The second one I consider a unit test and assures that a specific implementation is tested. I can control the dependencies and the interaction with them, but I need to stub each dependency and method used by \Foo\Bar
in order to successfully make the test pass, and because of it, I could make incorrect assumptions which could give me false sense of correctness. Multiple implementations of the same service could assume different . But, this is what I want as a developer of foobar_service
.
Creating both seems like a waste of effort… or doesn’t it?
Thanks