I'm putting together a set of models for use in a Zend Framework 2 application. So, each model has a table class which acts as the interface between the model and database for querying. Using the ZF2 TableGateway means that even a fairly simple query, like getting the number of hits from a page log between two dates, ends up with some complex calls:public function getDailyHits($start, $end){    $select = $this->tableGateway->getSql()->select();    $select->columns(array(            date => new Expression(DATE_FORMAT(timestamp, '%Y-%m-%d')),            hits => new Expression(COUNT(timestamp)),        ));    $select->where->between(timestamp, $start, $end);    $select->group(date);    $results = $this->tableGateway->selectWith($select);    $dailyHits = array();    foreach ($results as $result) {        $dailyHits[$result->date] = $result->hits;    }    return $dailyHits;}When it came to developing the unit test, I wrote up a bunch of expectations:public function testGetDailySearches(){    // Setup    $result = new \stdClass();    $result->date = 2015-01-01;    $result->searches = 42;    $resultSet = array($result);    $sql = $this->getMockBuilder(Zend\Db\Sql\Sql)        ->disableOriginalConstructor()        ->getMock();    $select = $this->getMockBuilder(Zend\Db\Sql\Select)        ->disableOriginalConstructor()        ->getMock();    $where = $this->getMockBuilder(Zend\Db\Sql\Where)        ->disableOriginalConstructor()        ->getMock();    $tableGateway = $this->getMockBuilder(Zend\Db\TableGateway\TableGateway)        ->disableOriginalConstructor()        ->getMock();    $searchLogTable = $this->getMockBuilder(Usage\Model\Table\SearchLog)        ->setConstructorArgs(array($tableGateway))        ->setMethods(null)        ->getMock();    // Expectations    $tableGateway->expects($this->once())        ->method(getSql)        ->will($this->returnValue($sql));    $tableGateway->expects($this->once())        ->method(selectWith)        ->with($this->equalTo($select))        ->will($this->returnValue($resultSet));    $sql->expects($this->once())        ->method(select)        ->will($this->returnValue($select));    $select->expects($this->once())        ->method(columns)        ->will($this->returnValue($select)); // TODO: need to assert parameters    $select->expects($this->once())        ->method(__get)        ->with($this->equalTo(where))        ->will($this->returnValue($where));    $where->expects($this->once())        ->method(between)        ->with(            $this->equalTo(time),            $this->equalTo(2015-10-01 00:00:00),            $this->equalTo(2015-10-07 23:59:59)        )        ->will($this->returnValue($select));    $select->expects($this->once())        ->method(group)        ->with($this->equalTo(date));    // Assertions    $this->assertEquals(        array(2015-01-01 => 42),        $searchLogTable->getDailySearches(2015-10-01 00:00:00, 2015-10-07 23:59:59)    );}I had a go at using Prophecy to reduce the verbosity in these tests, but got tripped up on them magic __get method needed to read the $where property from the Select object.After reading through a couple of threads on the Prophecy site, I uncovered a link to That's Not Yours. It makes a lot of sense. It also would reduce a lot of boilerplate in some tests if I just subclass TableGateway (or even maybe just mock it) so that all the Zend\Db behaviour is retained.But, then what happens to my expectations? Is this a case of overengineered testing? Should I have these expectations, or should I rely on testing a mostly black box of a method?If I did remove those expectations, and relied on a mocked result from the subclassed/mocked selectWith, I could write a passing test which didn't specify any of the select criteria, and would fail to function as required in the real world.
How to reconcile not mocking what you don't own with expectations in unit tests?
design;unit testing