How to add a CMS block programmatically in Magento 2?

add this to the your class:

private $blockFactory;

and make your constructor look like this:

public function __construct(
    PageFactory $pageFactory,
    \Magento\Cms\Model\BlockFactory $blockFactory
  )
{
    $this->pageFactory = $pageFactory;
    $this->blockFactory = $blockFactory;
}

you can even remove the $pageFactory dependency if you don't need it anymore.

Then replace:

$testPage = [
    'title' => 'Test page title',
    'identifier' => 'test-page',
    'stores' => [0],
    'is_active' => 1,
    'content_heading' => 'Test page heading',
    'content' => 'Test page content',
    'page_layout' => '1column'
];

$this->pageFactory->create()->setData($testPage)->save();

with

$testBlock = [
    'title' => 'Test block title',
    'identifier' => 'test-block',
    'stores' => [0],
    'is_active' => 1,
];
$this->blockFactory->create()->setData($testBlock)->save();

You can try the following solution:

Add 2 classes to the constructor:

/**
 * @var \Magento\Cms\Model\BlockFactory
 */
protected $blockFactory;

/**
 * @var \Magento\Cms\Model\BlockRepository
 */
protected $blockRepository;

/**
 * @param PageFactory $resultPageFactory
 * @param \Magento\Cms\Model\BlockFactory $blockFactory
 * @param \Magento\Cms\Model\BlockRepository $blockRepository
 */
public function __construct(
    PageFactory $resultPageFactory,
    \Magento\Cms\Model\BlockFactory $blockFactory,
    \Magento\Cms\Model\BlockRepository $blockRepository
) {
    $this->resultPageFactory = $resultPageFactory;
    $this->blockFactory = $blockFactory;
    $this->blockRepository = $blockRepository;
}

And use them in the following way:

$data = [
    'title' => 'Test block title',
    'identifier' => 'test-block',
    'stores' => ['0'],
    'is_active' => 1,
    'content' => 'Test block content'
];
$newBlock = $this->blockFactory->create(['data' => $data]);
$this->blockRepository->save($newBlock);

The code is working. Here is the result for this block:

enter image description here