8

I have a custom module that defines a service and a custom content type. I have successfully written a Functional test for the service. Now, I'm seeing if I can write a Kernel test instead.

The issue that I'm encountering is that my custom content type has custom fields (naturally). When I create a piece of content of that type in the Kernel test environment, Drupal is not recognizing the custom fields.

  • I am using the EntityKernelTestBase.
  • I have set public static $modules = array('my_custom_module', 'node');

What piece(s) am I missing? I'm guessing there is some schema I need to say to install or some other method I need to call so that those custom fields are recognized.

<?php

namespace Drupal\Tests\my_custom_module\Kernel;

use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\node\Entity\Node;

/**
 * Tests the my custom service.
 *
 * @group my_custom_module
 */
class MyCustomServiceKernelTest extends EntityKernelTestBase {

  /**
   * Modules to install.
   *
   * @var array
   */
  public static $modules = array('my_custom_module', 'node');

  /**
   * {@inheritdoc}
   */
  public function setUp() {

    parent::setup();

    $user = $this->createUser();

    $container = \Drupal::getContainer();
    $container->get('current_user')->setAccount($user);

    // Create some aquifer pieces of content
    $node = Node::create(array(
      'title' => t('Some title'),
      'type' => 'my_custom_content_type',
      'language' => 'en',
      'field_my_custom_field_1' => 'Put stuff here',
      'field_my_custom_field_2' => 'more stuff',
      'field_my_custom_field' => 1000000,
    ));
    $node->save();
    $reloaded_entity = $this->reloadEntity($node);
    $this->assertSame('debug', $reloaded_entity);
  }
}

The debug assert statement shows that the reloaded entity does not contain my custom fields.

If I put a $node->set('field_my_custom_field_1', 'some value') statement in the code instead of passing those fields in the Node::create logic I get an error that the field name is not valid.

2 Answers 2

10

For kernel tests you need to specify which configurations you want installed. For instance, you'll need something like this in your test's setUp() method:

$this->installConfig(['my_custom_module']);

That takes an array of modules, so you'll probably need to specify additional modules (like filter, node, and field potentially).

This assumes your field configurations are bundled in your module's config/install directory.

10
  • Thanks for the suggestion. I have used $this->installConfig(['my_custom_module']) as you are suggesting and I still have the same problems. Since I'm using the EntityKernelTestBase some of the other stuff you mention is taken care of in there. I'm going to update my question with more details about what I've got already. Mar 3, 2017 at 21:17
  • 1
    To follow up on your other point, I have defined the custom content type via the config/optional directory. (Recall that the full Functional test works just fine. So, the issue is definitely that I'm missing some things I need to explicitly tell the Kernel test to do.) Mar 3, 2017 at 21:25
  • Just to test things out, I have included $this->installConfig(['node', 'my_custom_module']); and the $reloaded_entity still does not contain my custom fields. Mar 3, 2017 at 21:33
  • 2
    Anything in config/optional will only be installed if all dependencies are met, so you could look at your content type, and see which modules it requires, then make sure to enable those as well. For testing purposes, try moving it to config/install, and then when the test is run, any missing dependencies should be printed out in an exception.
    – jhedstrom
    Mar 3, 2017 at 21:42
  • 2
    Here's the heart of what I needed to do to get it to work. I did need to enable more modules public static $modules = []; and I did need to install some configuration $this->installConfig([]);. In my case I needed to $this->installConfig(['node', 'my_custom_module']);. Yes, it DOES matter if node's configuration is installed first because my_custom_module defines a new content type. It did not matter whether I used config/install or config/optional and I chose to keep things in config/optional. Mar 5, 2017 at 3:22
1
  1. It's not necessary to put your modules configs to config/install. Let the config in config/optional

  2. Important: check the module dependencies

    a) for your content type ('my_custom_content_type') by opening the config file node.type.my_custom_content_type.yml,

    b) for the special fields like 'text' (that need additional modules) by opening field.storage.node.MY_SPECIAL_FIELD.yml

yaml field

dependencies:
  module:
    - DEP_MODULE_N
  1. Add installing modules 'DEP_MODULE_N' and 'my_custom_module' and needed schema:
class ImportBatchKernelTest extends KernelTestBase {

  protected static $modules = [
    'system',
    'user',
    'DEP_MODULE_1',
    'field',
    'node',
    'DEP_MODULE_2',
    'my_custom_module',
  ];

protected function setUp() : void {
    parent::setUp();

    $this->installEntitySchema('user');
    $this->installEntitySchema('node');
    $this->installSchema('node', 'node_access'); // <-- needed at least for entity reference fields, just test :-)
    $this->installConfig(['node', 'my_custom_module']);
  }

...
...
  1. The modules 'system', 'user', 'field', 'node' are needed for testing manipulations of nodes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.