Mocking in phpunit

To test a class in PHPUnit, it's easier if you use dependency injection which enables you to mock other classes that we aren't interested in testing (such as your database layer). So for example, instead of writing code like this to test a made-up User class:

class User() {
    private $db;

    function __construct()
    {
        $this->db = new Database;
    }

    function getUserData()
    {
        return $this->db->getUserData();
    }
}

$user = new User();

We can pass in the database class instead:

class User() {
    private $db;

    function __construct($db) {
        $this->db = $db;
    }

    function getUserById($userid) {
        return $this->db->getUserData($userid);
    }
}

$db = new Database; $user = new User($db);

This means that we can mock the Database object when we're testing the User class, and pass the former into the latter. We do this as PHPUnit won't override the new keyword

In PHPUnit, it's a case of creating the class but in place of using the new keyword we use a slightly longer one instead:

$mockDb = $this->getMock( 'Database', array('getUserData') );
$mockDb->expects($this->any())
                      ->method('getUserData')
                      ->with('joebloggs')
                      ->will($this->returnValue(
                          array('userid' => 'joebloggs', 'name' => 'Joe Bloggs')
                 );

$user = new User($mockDb);
$this->assertEquals( $user->getUserById('joebloggs'), array('joebloggs', 'Joe Bloggs') )

In a nutshell, those two commands says what the class should be, and what the method should expect and return respectively. To break down what each bit of the two commands do:

  • getMock() is saying mock the class given in the 1st parameter, and we want to return given values for the methods given in the array in the 2nd parameter

  • The second command has a bit more too it. expects($this->any()) will mean that it doesn't matter whether the method gets called or not - changing it to expects($this->once()) will mean that if the method isn't called (or is called more than once) the test will fail

  • with() is the parameters that you should expect to be passed in (which is a good way to check that the parameters that's being passed into a particular method are sane), and will($this->returnValue()) is what you want to give as the known return value, for when you do your test

Of course, there's much more you can do with PHPUnit mocking. The documentation is a pretty good start to find out what else is there.

Setting the proxy for command-line OS X

In OS X, it's pretty simple to set a Location to set a proxy for whenever you're somewhere you need to use one

However, this doesn't affect some commandline applications, such as Homebrew. If you want to send this through a proxy, you'll have to edit .curlrc to read something like

proxy = proxy.example.com:8080

Files not loading in a Virtualbox virtual machine

Every so often, randomly I see a problem where a virtual machine will only partly load a CSS or Javascript file, and when you load it in the browser it will have a bunch of strange unicode characters in there

We even saw it in joind.in

The fix is fairly simple - just edit your vhost configuration and add the following lines:

EnableMMAP Off EnableSendfile Off

Switching branches in Subversion without losing changes

The problem: you want to switch branches in Subversion, but you've got changes in your local code that you're not ready to commit

The solution: export a patch that you can store somewhere safe (or even commit into the repo so others can see it or work on it)

To export all changes, use svn diff to create a patch file:

svn diff > fix-that-annoying-bug.diff

As a sidenote, if I'm using a bug tracker, I like to put the bug ID in the filename: not only does this keep all the different projects together, it makes it easy to know what exactly the code changes does:

svn diff > myproject-1234-fix-that-annoying-bug.diff

From there I can revert all changes and switch branch:

svn revert -R . svn switch http://svn.example.com/my-new-branch/

Once I'm done with the new branch and want to go back, and assuming I've committed all my changes I switch back to my old branch:

svn switch http://svn.example.com/my-original-branch/

And I import my original changes patch file to start work again, carrying on from where I left off:

patch -p0 -i fix-that-annoying-bug.diff

Transparent/broken HTML form validation warnings in Webkit and Firefox

In the latest versions of Chrome and Firefox, if you use the new bits of HTML forms such as validation (the ‘required’ attribute) and the ‘email’ type, there’s now some validation.

If you was to enter something that wasn’t a valid email address, or left the field empty if it was required, you’d get a nice looking tooltip notification as such:

Image removed.

But sadly, if you use some popular CSS resets such as the lovely one made by Meyer, you’ll get something that looks like this:

Image removed.

The fix is to look for code similar to this in the reset:

html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; }

And replace the div selector with body div

Problems with attributes not working in IE and Opera?

So, what did I do with my bank holiday weekend? I was intrigued by some odd Opera and IE behaviour — that’s what

I was presented with a site whose styling wasn’t working for certain tags. It was an odd one. I thought it might be an absolute positioning bug, but testing was bringing up nothing – why on earth would simple CSS styling, nothing special, fail completely in Opera?

Then I took a closer look at the source — and something caught my eye. There was some malformed HTML:

<h1 title="test""style="background-color: #ccc">Test</h1>

Gotcha! Removing that innocent looking multiple quote fixed the problem. But I still wasn’t happy. Browsers should recognise and fix badly formed HTML, no? It’s not like a closing tag was completely missing. So I made a basic HTML template with little more than the h1 tag you see above, and just enough HTML5 to make it validate.

Then I played around with it. What happens if I add a space?

<h1 title="test"" style="background-color: #ccc">Test</h1>

That fixed it. Hm. Why on earth would the lack of space break things? Lacking a space is completely fine in both HTML and XHTML. Let’s remove the space again, and test some more. What if I replace the rogue ” with another character – say $?

<h1 title="test"$style="background-color: #ccc">Test</h1>

Wait — that’s a turnout for the books — it now breaks in Chrome. Then it dawned on me. If I replace that dollar sign with a normal alphanumeric character — the character ‘a’:

<h1 title="test"astyle="background-color: #ccc">Test</h1>

That’s it! Without the space between attributes, Opera and Internet Explorer are treating “style as the attribute, with Webkit and Gecko being smart and removing the extra quote. Add the space, and Webkit does the same. Obvious when you think about it, isn’t it?

So that’s what I did with my bank holiday weekend. What did you do?

Reusing primary keys in MySQL

I’ve recently had need to reuse the primary key for a table whenever a row gets deleted, for example if a row of ID 5 gets deleted, the next entry will re-use the ID of 5. Usually this causes problems with foreign keys, but as no other table had a foreign key linked to this table, it would cause no problems.

The biggest hurdle was finding what the first missing primary key actually is. This takes a bit of SQL, but the following almost gets it:

SELECT MIN(table.id + 1) AS nextID FROM table LEFT JOIN table t1 ON table.id + 1 = t1.id WHERE t1.id IS NULL

I say almost, because if row/id 1 is deleted, the above code won’t catch it. I’m afraid that you’ll have to useSELECT to check for this:

SELECT count(id) FROM table WHERE id = 1

If the value is 0, then you know you need to create row id 1.

And that’s it. All you need to do is throw this together into a MySQL function (or a php function if you’re not feeling adventurous), and you have the lowest unused primary key all ready for you to put into yourINSERT line.