Writing mocks / stubs for an object before you wrote a class for this object?

I am developing a class that has two dependencies. One of the dependency classes has been written and tested. The other is not written yet.

It seemed to me because the remaining dependency would be written to make it easier for the class to use it so that I write the last one first and also develop the interface of the first one when I go and find out what it should do.

It seems to me that this is a great way to make code. In the end, as long as the main class gets the layout in its constructor, I can write it and test it without realizing that its dependency does not exist, then I can create the dependency as soon as I'm sure I know what I need .

So: how do I do this? Create a skeleton class that I change as I move. Maybe something like:

class NonExistantSkeleton { public function requiredMethod1() { } public function newlyDiscoveredRequirement() { } } 

and then mock it with PHPUnit and setting up stubs, etc. to keep the class under development happy?

Is that the way?

This seems to be a good way to develop code - and it seems to me that it makes more sense than developing dependency, not knowing exactly how it will be used.

+8
php class-design phpunit
source share
2 answers

In short:

Yes. At least that's what I'm doing right now.


Longer version:

If the expected co-authors of your class do not exist at the moment when you need them in the tests for the class you are building, you have several options :

  • Layout of nonexistent classes (which phpunit can do)
  • Create class skeletons and mock them
  • Just create interfaces and get mocks for those (which phpunit can do too)
  • Perhaps you do not need any of the above depending on the object

If you are programming against an interface , since all you have to do is create this interface and tell PHPUnit to create a / mock stub from it

  • + No new class without test
  • + Using interfaces, when appropriate, is considered better / better than just hinting at classes

When it makes fun of non-existing classes , you get some flaws that I don't like:

  • - High maintenance costs
  • -Keeping methods on these classes is slow and tedious
  • -If you created a class, you must rework mocks again

so I would consult with that.

the middle way would be to simply create an empty skeleton of the class with its method and use them for bullying.

I really like this in cases where there is no interface for a hint, since it is fast and creates stable test code.

Having barebone classes with public apis is, for me, not a violation of TDD.


There are classes you don't need to make fun of.

Data Transfer Objects and Value Objects can always be created anywhere using new in your production code, so your tests can also only be real objects .

This helps keep your tests a little cleaner, since you don't have to scoff / expect a lot of getter / setter methods, etc.

+8
source share

If you follow the test-driven development methodology, then the usual approach is as follows:

  • Find out what your classes should do and what their public-oriented APIs should be.
  • Implement "empty" classes, which consist of nothing but public methods, with empty bodies (as you did in the code example you provided).
  • Develop an implementation strategy. This means that which classes depend on each other and implement them in the order, which means that the dependent classes are not executed until the classes on which it depends are finished or at least functional enough for development. This means that classes without dependencies are executed first, and then classes that depend only on completed classes, etc.
  • Write your tests. Now you can write tests, because you know what the black box for your classes looks like, what they need to accept as input, and what they should return as output.
  • Run the tests. You should get 0% success, but also 100% code coverage. Now this is your base level.
  • Start implementing your classes according to your implementation strategy. Run your unit tests periodically during this process, say as soon as you finish the class to make sure that it meets its specifications, as indicated in the unit test. Ideally, each test should show an increase in test passes while maintaining 100% code coverage.

EDIT: As edorian noted, PHP interfaces are a huge help here because PHPUnit can generate mocks and stubs from interfaces as well as from classes. They are also an excellent tool for reducing traction and improving overall displacement. They allow you to replace any class that implements the expected interface, rather than just subclasses of the expected class.

+7
source share

All Articles