Using subcontexts with Behat and Mink

Using subcontexts with Behat and Mink is easy. You only need to remember to only extend MinkContext (or use Mink as subcontext) once, because it has some basic step definitions already defined and Behat doesn’t allow redundant step definitions.

My base FeatureContext file looks something like the below:

<?php
 
use Behat\Behat\Context\ClosuredContextInterface,
    Behat\Behat\Context\TranslatedContextInterface,
    Behat\Behat\Context\BehatContext,
    Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode,
    Behat\Gherkin\Node\TableNode;
 
use Behat\MinkExtension\Context\MinkContext;
use Behat\Behat\Context\Step;
 
/**
 * Features context.
 */
class FeatureContext extends MinkContext
{    
    public function __construct(array $parameters)
    {
        // Initialize your context here
        // ...
        $this->useContext('SubContext', new SubContext($parameters));
    }
}

And here’s my SubContext template file:

<?php
 
use Behat\Behat\Context\ClosuredContextInterface,
    Behat\Behat\Context\TranslatedContextInterface,
    Behat\Behat\Context\BehatContext,
    Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode,
    Behat\Gherkin\Node\TableNode;
 
use Behat\Behat\Context\Step;
 
/**
 * Features context.
 */
class SubContext extends BehatContext
{
    /**
     * Initializes context.
     * Every scenario gets it's own context object.
     *
     * @param array $parameters context parameters
     */
    public function __construct(array $parameters)
    {
        // Initialize your context here
        // ...
    }
 
    /**
     * Get Mink session from MinkContext
     */
    public function getSession($name = null)
    {
        return $this->getMainContext()->getSession($name);
    }
 
    /**
     * Write your subcontext methods below.
     * Remember that this class extends BehatContext, not MinkContext
     */
 
}

Note that it extends BehatContext and not MinkContext as this is not allowed – I used MinkContext already as a base of my FeatureContext class.

Also, the getSession() proxy method is created, as it is probably the most used one across the suite.

Now, whenever you want to call a method from main context, use:

$this->getMainContext()->methodName($args);

To communicate between subcontexts use:

$this->getMainContext()->getSubcontext('SubContext')->methodName($args);

Comments

  1. Diego Lewin on

    Thanks, I had the redundant step definitions exception :)

    Reply
  2. cmorell85 on

    Excelent!!!Thanks a lot!

    Reply
  3. Jonathan RAMIER on

    thanks a lot, I resolved my exception with your post

    Reply
  4. Max Heckel on

    Helped me get it working! Thanks!

    Reply
  5. matthewmarichiba on

    Thanks for this. I’m not sure why this content isn’t part of the core Mink docs. I presume everyone eventually wants to break their step definitions into multiple files, given a big enough project, but Behat & Mink docs don’t make it obvious how to do so. The way you’ve laid it out here worked for me and seems elegant.

    Reply

Leave a Reply