简体   繁体   中英

Stuck on mocking 3 classes for 1 unit test

In Authentication.php I have the following function I would like to create a test for:

function showModal() {
  $registration = new Registration;
  $registration->needShowModal = Store::isUserSupported() ? false : true;
}

In my test case so far, I have a mocked Store:

function testShowModal() {
        $mockStore = $this->getMockClass(‘Store', array('isUserSupported'));

        $mockStore::staticExpects($this->any())
            ->method('isUserSupported')
            ->will($this->returnValue(true)); 
}

I'm guessing that next I need to create a mockRegistration and pass that and the mockStore into the Authentication controller, something along the lines of:

$controller = new Authentication($mockStore,$mockRegistration);

However, when I create Authentication it keeps complaining that it expects a request and response object as the first 2 params.. so maybe that's not the right way.

How can I best write a test for isUserSupported == true and isUserSupported == false? I'm dealing with 3 different classes in this test so that's where I'm getting stuck.

As your method is written, you are not able to pass any mocks to replace your objects.

You are calling new Registration which will create an instance of the actual class rather than using the mock.

The static call Store::isUserSupported() will also call the actual method. staticExpects only works when testing the class that is being called statically (You have a static method that calls a different method in the same class). So that mock will not work.

To make it testable the method should become something like this:

function showModal($registration, $store) {
  $registration->needShowModal = Store->isUserSupported() ? false : true;
}

Now you would be able to create mocks for the dependencies and pass them into the method.

Though it does seem that you are testing an action on a MVC framework controller. In my experience, for testing the controllers your tests end up being more "integration" rather than "unit". Rather than trying to control these dependencies, try to control the data source that is being used and make sure the response comes back set appropriately with the proper request. This also gives you the benefit of knowing that other classes (which all have been tested as well) have their assumptions right about what is being passed to them.

Without knowing more about the framework or the rest of the code, that is the best that I am able to do.

Check out the Factory Pattern . What I would do in this situation if you do not want to pass it in as a parameter, is have a seperate class that creates the Registration object for you. Among other benefits, you would then just need to mock your new class to return a Registration object(real or mocked!) when you call createRegistrationObject() on your new class.

I ended up doing the following: 1. mocking the config values 2. calling a getPublicClass function on the mocked controller 3. calling mockedController->testFunction()

This was a while ago so I'm 100% on the specifics but I noticed it wasn't answered so just wanted to update what I did based on looking at the final code. Thanks!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM