For service methods that call repository methods to interact with database how could I unit test these service methods?
For example,
public function updateSlideshow($data){
// do some logic and method calls (I can test those methods,
// but for this method that call repository ...)
$r = $this->blockRepo->update($data, $config, $slides);
}
How can I check that this method work correctly or at least send right data to update method?
And what about a scenario that method first fetch data from repository and do logic on it?
2 Answers 2
Assuming you are using dependency injection, then this situation is easily solved. You will be injecting blockRepo
into the class/module containing updateSlideshow
. So in a live environment, you inject a version of blockRepo
that talks to a DB. In a test environment, you inject a version that mocks this behaviour, eg reads/writes to local variables, rather than a DB, allowing you to simulate various DB data states for the various tests.
-
An important thing to add is the repository class should implement an interface that your mock can implement. The repository argument in your constructor should have a PHP type hint for the interface.Greg Burghardt– Greg Burghardt2016年01月13日 11:31:47 +00:00Commented Jan 13, 2016 at 11:31
-
@GregBurghardt. Ah, thanks. I wasn't sure if PHP supported interfaces, so I tried to make my answer generic. Since it does support them, then I agree 100% with you that interfaces should be used.David Arno– David Arno2016年01月13日 11:39:38 +00:00Commented Jan 13, 2016 at 11:39
-
what would be your assert for service ?Arash– Arash2018年10月10日 06:00:54 +00:00Commented Oct 10, 2018 at 6:00
Don't unit test them, at least at first. Use an integration test which brings up an empty database with your DDL loaded, runs this method with some inputs, and asserts on the result data or result behavior.
Having that integration test in place will be a good stepping stone for creating a test double. Code your db-interacting code against an interface which your db class implements. You can then make a test double implementation that uses a Map locally to provide the same interface. That double can be passed along to other pieces of code which depend on database functionality. The integration test you wrote for the full database version can be used to cross-check that the test double exposes correct behavior.
-
1reminds me of my own question: programmers.stackexchange.com/questions/297944/… if there is almost no logic in the function its better to do integration rather than unit testing in my opinion tooarisalexis– arisalexis2016年01月12日 20:57:03 +00:00Commented Jan 12, 2016 at 20:57
Explore related questions
See similar questions with these tags.
updateSlideshow
, you are not testing theRepository::update
method. If you want to test that one, create a specific test only for it. You can also use integration testing to test the whole flow, note that integration tests have side effects.