2

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?

mohsenJsh
  • 1,237
  • 1
  • 10
  • 15
  • 2
    Using mocking to mock the repository and its behaviour for testing purposes. A mocking framework will be helpful. – Bernard Jan 12 '16 at 19:43
  • You are testing the `updateSlideshow`, you are not testing the `Repository::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. – Andy Jan 13 '16 at 11:30

2 Answers2

4

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.

David Arno
  • 38,972
  • 9
  • 88
  • 121
  • 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 Jan 13 '16 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 Jan 13 '16 at 11:39
  • what would be your assert for service ? – Arash Oct 10 '18 at 06:00
1

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.

Daenyth
  • 8,077
  • 3
  • 31
  • 46
  • 1
    reminds me of my own question: http://programmers.stackexchange.com/questions/297944/how-to-test-a-rest-service-without-being-excessive if there is almost no logic in the function its better to do integration rather than unit testing in my opinion too – arisalexis Jan 12 '16 at 20:57