Hacker News new | ask | show | jobs
by wanderr 4641 days ago
Perhaps I'm missing something, what about static methods prevents you from having a mock AuthorizeNet class implementing the same interface but with a submit() method that just returns fake data? Perhaps there is something specific to the testing framework you use that makes this clunky?

As far as static properties go, if you're mucking with those you're back into the world of storing state, which OO is more suitable for, but the whole point is to avoid doing that wherever possible. :) What I was getting at before is that we really use a mixture of both real OO and procedural with class-namespaces-static-methods wherever each thing makes sense, but given the nature of what most backend PHP is trying to accomplish, the latter ends up being the majority.

2 comments

In this case, you are probably just using classes to emulate namespaced functions [1], the use of 'class' is confusing to oop programmers, the code does not have classes, just the word class.

Like php code, php itself is often confusing and hard to decipher, currently I think it of it as a C dsl for web stuff that people mistake for a high level application framework.

Like C, many people learn basic syntax and functionality in school or as a side project. Unlike C, people believe that that their skillset is the one required to build a complex server side application combined with a web ui.

If you realize the mismatch and account for it, you can build great php websites. The problem arises when people assume they are getting a 'faster/cheaper' .Net/Java stack and start to hire programmers into that structure.

The net result is a clash between people that are using PHP as intended, and people that have been subjected to the misuse of the php.

1. http://stackoverflow.com/questions/5647598/cannot-import-use...

I am completely against create actual files to make mocks.

I use PHPUnit, the de facto standard for testing php code.

To create a proper mock in it, you use getMockBuilder()

Why can't you use getMockBuilder() for static methods? (I don't know PHPUnit so maybe it's a stupid question.)
These tools only work when:

1) You've implemented dependency injection, or

2) You're using a container

For example, in PHP you can't mock something like "$foo = new Bar();". The code is right there, it's saying exactly what it wants, you can't return a fake class (unless you do some ugly magic).

However, you can pass in an object that is_a Bar, either injecting it via DI or storing it and then retrieving it from a container.

With code like Foo::Bar() - that's it. You're tied to the Foo class, Bar() method and you can't change a thing about this.

Procedural testing isn't hard.

All that dependency crap is only a result of your AbstractTestingFrameworkMethodFactoryClassMockMethodGenerator() and similarly useless abstractions, anyway.

A simple module system can be implemented in a single function and referenced from test code as easily as:

test_requires('module1','module2');

Purely procedural tests are as easy as:

assert_equals(function_one('example_input'),'expected_output'); assert_not_equals(function_two(true),false);

Full featured test framework:

function assert_equals($a,$b) { return $a==$b; } function assert_not_equals($a,$b) { return $a!=$b; }

(Edit: I don't believe I missed the point - 'dependency injection', a recent term in PHP, essentially means tightly coupling to an entire DI system instead of directly to a single dep as demonstrated above. Either way, loose coupling is a concept to strive for as far as reasonably possible - not an absolute requirement. If your code requires something else, then it requires something else. The solution is not to create a new AbstractPretenderOfTotalWorldVisibilityEvenThoughControlFlowIsNowAllOverTheShop() After all, if you carry that tight coupling argument further you could claim that by virtue of writing PHP at all you are tight coupling to a certain, if broad, class of processor architectures. There has to be a limit somewhere! Mostly, that's determined by legibility/maintaintability and programmer time, not by abstract measures of correctness.)

I think you've missed the point. If your procedure calls other procedures, how do you test its functionality individually? How do you know if the problem exists in the procedure itself or one of the procedures it calls. Without DI in some form you are stuck with your procedures being tightly coupled together.
You can still mock the Foo class... by using class_alias.

Don't tell anyone else, though :p