I am relatively new to mocking and I assume I have a fundamental misunderstand how PHPunit mocks work and how they are supposed to be used. My SUT (subject under test) contains a class which is not default-constructible and for which I want to replace a single method with a mock.
Let's assume the class I want to mock looks like this
class MyClass {
protected int $someValue;
protected string $anotherValue;
public function __construct(array $param1, int $param2) {
// does something, among other things
// initializes $this->someValue and $this->anotherValue
}
public function doSomething(string $a): array {
// ...
}
public function doSomethingElse(bool $a): array {
// ...
}
public function isOpen(): bool {
// here some real logic happens based on the inner state of the object
}
}
My SUT uses this class throughout the code and creates objects of this class as needed.
I want to proxy this class in the following sense
- If the SUT creates a new object of the class, a proxy object (i.e. the mock) is created and the proxy class (aka mock) creates an object of
MyClassinternally forwarding the arguments of the constructor - If the SUT calls any method of the object, the original methods (with the correct parameters) are invoked on the original object.
- If the SUT class
isOpenthe mock always returnsfalse.
So this is what I tried
class MyTest extends PHPUnitTestClass {
public function testWithMock: void {
$proxy = $this->getMockBuilder(MyClass::class)
->enableOriginalConstructor()
->enableOriginalClone()
->enableProxyingToOriginalMethods()
->disableArgumentCloning()
->getMock();
$proxy->method('isOpen')->willReturn(false);
// ... the actual test
}
}
The code already fails in the first statement, because obviously MockBuilder tries to construct the original class upon getMock. This is not what I need. I don't need a single instance of the original class inside the mock object. I want to create a new object of the original class whenever the SUT calls new and I only want to change the behavior of a single method.