Merge pull request #53540 from nextcloud/feature/add-profile-to-occ

Feature/add profile to occ
pull/53548/head
Richard Steinmetz 2025-06-17 16:12:43 +07:00 committed by GitHub
commit a1cf92ceed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 722 additions and 27 deletions

@ -0,0 +1,234 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OC\Core\Command\User;
use OC\Core\Command\Base;
use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\PropertyDoesNotExistException;
use OCP\IUser;
use OCP\IUserManager;
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class Profile extends Base {
public function __construct(
protected IUserManager $userManager,
protected IAccountManager $accountManager,
) {
parent::__construct();
}
protected function configure() {
parent::configure();
$this
->setName('user:profile')
->setDescription('Read and modify user profile properties')
->addArgument(
'uid',
InputArgument::REQUIRED,
'Account ID used to login'
)
->addArgument(
'key',
InputArgument::OPTIONAL,
'Profile property to set, get or delete',
''
)
// Get
->addOption(
'default-value',
null,
InputOption::VALUE_REQUIRED,
'(Only applicable on get) If no default value is set and the property does not exist, the command will exit with 1'
)
// Set
->addArgument(
'value',
InputArgument::OPTIONAL,
'The new value of the property',
null
)
->addOption(
'update-only',
null,
InputOption::VALUE_NONE,
'Only updates the value, if it is not set before, it is not being added'
)
// Delete
->addOption(
'delete',
null,
InputOption::VALUE_NONE,
'Specify this option to delete the property value'
)
->addOption(
'error-if-not-exists',
null,
InputOption::VALUE_NONE,
'Checks whether the property exists before deleting it'
)
;
}
protected function checkInput(InputInterface $input): IUser {
$uid = $input->getArgument('uid');
$user = $this->userManager->get($uid);
if (!$user) {
throw new \InvalidArgumentException('The user "' . $uid . '" does not exist.');
}
// normalize uid
$input->setArgument('uid', $user->getUID());
$key = $input->getArgument('key');
if ($key === '') {
if ($input->hasParameterOption('--default-value')) {
throw new \InvalidArgumentException('The "default-value" option can only be used when specifying a key.');
}
if ($input->getArgument('value') !== null) {
throw new \InvalidArgumentException('The value argument can only be used when specifying a key.');
}
if ($input->getOption('delete')) {
throw new \InvalidArgumentException('The "delete" option can only be used when specifying a key.');
}
}
if ($input->getArgument('value') !== null && $input->hasParameterOption('--default-value')) {
throw new \InvalidArgumentException('The value argument can not be used together with "default-value".');
}
if ($input->getOption('update-only') && $input->getArgument('value') === null) {
throw new \InvalidArgumentException('The "update-only" option can only be used together with "value".');
}
if ($input->getOption('delete') && $input->hasParameterOption('--default-value')) {
throw new \InvalidArgumentException('The "delete" option can not be used together with "default-value".');
}
if ($input->getOption('delete') && $input->getArgument('value') !== null) {
throw new \InvalidArgumentException('The "delete" option can not be used together with "value".');
}
if ($input->getOption('error-if-not-exists') && !$input->getOption('delete')) {
throw new \InvalidArgumentException('The "error-if-not-exists" option can only be used together with "delete".');
}
return $user;
}
protected function execute(InputInterface $input, OutputInterface $output): int {
try {
$user = $this->checkInput($input);
} catch (\InvalidArgumentException $e) {
$output->writeln('<error>' . $e->getMessage() . '</error>');
return self::FAILURE;
}
$uid = $input->getArgument('uid');
$key = $input->getArgument('key');
$userAccount = $this->accountManager->getAccount($user);
if ($key === '') {
$settings = $this->getAllProfileProperties($userAccount);
$this->writeArrayInOutputFormat($input, $output, $settings);
return self::SUCCESS;
}
$value = $this->getStoredValue($userAccount, $key);
$inputValue = $input->getArgument('value');
if ($inputValue !== null) {
if ($input->hasParameterOption('--update-only') && $value === null) {
$output->writeln('<error>The property does not exist for user "' . $uid . '".</error>');
return self::FAILURE;
}
return $this->editProfileProperty($output, $userAccount, $key, $inputValue);
} elseif ($input->hasParameterOption('--delete')) {
if ($input->hasParameterOption('--error-if-not-exists') && $value === null) {
$output->writeln('<error>The property does not exist for user "' . $uid . '".</error>');
return self::FAILURE;
}
return $this->deleteProfileProperty($output, $userAccount, $key);
} elseif ($value !== null) {
$output->writeln($value);
} elseif ($input->hasParameterOption('--default-value')) {
$output->writeln($input->getOption('default-value'));
} else {
$output->writeln('<error>The property does not exist for user "' . $uid . '".</error>');
return self::FAILURE;
}
return self::SUCCESS;
}
private function deleteProfileProperty(OutputInterface $output, IAccount $userAccount, string $key): int {
return $this->editProfileProperty($output, $userAccount, $key, '');
}
private function editProfileProperty(OutputInterface $output, IAccount $userAccount, string $key, string $value): int {
try {
$userAccount->getProperty($key)->setValue($value);
} catch (PropertyDoesNotExistException $exception) {
$output->writeln('<error>' . $exception->getMessage() . '</error>');
return self::FAILURE;
}
$this->accountManager->updateAccount($userAccount);
return self::SUCCESS;
}
private function getStoredValue(IAccount $userAccount, string $key): ?string {
try {
$property = $userAccount->getProperty($key);
} catch (PropertyDoesNotExistException) {
return null;
}
return $property->getValue() === '' ? null : $property->getValue();
}
private function getAllProfileProperties(IAccount $userAccount): array {
$properties = [];
foreach ($userAccount->getAllProperties() as $property) {
if ($property->getValue() !== '') {
$properties[$property->getName()] = $property->getValue();
}
}
return $properties;
}
/**
* @param string $argumentName
* @param CompletionContext $context
* @return string[]
*/
public function completeArgumentValues($argumentName, CompletionContext $context): array {
if ($argumentName === 'uid') {
return array_map(static fn (IUser $user) => $user->getUID(), $this->userManager->search($context->getCurrentWord()));
}
if ($argumentName === 'key') {
$userId = $context->getWordAtIndex($context->getWordIndex() - 1);
$user = $this->userManager->get($userId);
if (!($user instanceof IUser)) {
return [];
}
$account = $this->accountManager->getAccount($user);
$properties = $this->getAllProfileProperties($account);
return array_keys($properties);
}
return [];
}
}

@ -92,6 +92,7 @@ use OC\Core\Command\User\ClearGeneratedAvatarCacheCommand;
use OC\Core\Command\User\Info;
use OC\Core\Command\User\Keys\Verify;
use OC\Core\Command\User\LastSeen;
use OC\Core\Command\User\Profile;
use OC\Core\Command\User\Report;
use OC\Core\Command\User\ResetPassword;
use OC\Core\Command\User\Setting;
@ -206,6 +207,7 @@ if ($config->getSystemValueBool('installed', false)) {
$application->add(Server::get(Report::class));
$application->add(Server::get(ResetPassword::class));
$application->add(Server::get(Setting::class));
$application->add(Server::get(Profile::class));
$application->add(Server::get(Command\User\ListCommand::class));
$application->add(Server::get(ClearGeneratedAvatarCacheCommand::class));
$application->add(Server::get(Info::class));

@ -1331,6 +1331,7 @@ return array(
'OC\\Core\\Command\\User\\Keys\\Verify' => $baseDir . '/core/Command/User/Keys/Verify.php',
'OC\\Core\\Command\\User\\LastSeen' => $baseDir . '/core/Command/User/LastSeen.php',
'OC\\Core\\Command\\User\\ListCommand' => $baseDir . '/core/Command/User/ListCommand.php',
'OC\\Core\\Command\\User\\Profile' => $baseDir . '/core/Command/User/Profile.php',
'OC\\Core\\Command\\User\\Report' => $baseDir . '/core/Command/User/Report.php',
'OC\\Core\\Command\\User\\ResetPassword' => $baseDir . '/core/Command/User/ResetPassword.php',
'OC\\Core\\Command\\User\\Setting' => $baseDir . '/core/Command/User/Setting.php',

@ -1372,6 +1372,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Command\\User\\Keys\\Verify' => __DIR__ . '/../../..' . '/core/Command/User/Keys/Verify.php',
'OC\\Core\\Command\\User\\LastSeen' => __DIR__ . '/../../..' . '/core/Command/User/LastSeen.php',
'OC\\Core\\Command\\User\\ListCommand' => __DIR__ . '/../../..' . '/core/Command/User/ListCommand.php',
'OC\\Core\\Command\\User\\Profile' => __DIR__ . '/../../..' . '/core/Command/User/Profile.php',
'OC\\Core\\Command\\User\\Report' => __DIR__ . '/../../..' . '/core/Command/User/Report.php',
'OC\\Core\\Command\\User\\ResetPassword' => __DIR__ . '/../../..' . '/core/Command/User/ResetPassword.php',
'OC\\Core\\Command\\User\\Setting' => __DIR__ . '/../../..' . '/core/Command/User/Setting.php',

@ -0,0 +1,470 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Core\Command\User;
use OC\Core\Command\User\Profile;
use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\IAccountProperty;
use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Test\TestCase;
class ProfileTest extends TestCase {
protected IAccountManager&MockObject $accountManager;
protected IUserManager&MockObject $userManager;
protected IDBConnection&MockObject $connection;
protected InputInterface&MockObject $consoleInput;
protected OutputInterface&MockObject $consoleOutput;
protected function setUp(): void {
parent::setUp();
$this->accountManager = $this->createMock(IAccountManager::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->connection = $this->createMock(IDBConnection::class);
$this->consoleInput = $this->createMock(InputInterface::class);
$this->consoleOutput = $this->createMock(OutputInterface::class);
}
public function getCommand(array $methods = []): Profile|MockObject {
if (empty($methods)) {
return new Profile($this->userManager, $this->accountManager);
} else {
return $this->getMockBuilder(Profile::class)
->setConstructorArgs([
$this->userManager,
$this->accountManager,
])
->onlyMethods($methods)
->getMock();
}
}
public static function dataCheckInput(): array {
return [
'Call with existing user should pass check' => [
[['uid', 'username']],
[],
[],
true,
null,
],
'Call with non-existing user should fail check' => [
[['uid', 'username']],
[],
[],
false,
'The user "username" does not exist.',
],
'Call with uid, key and --default value should pass check' => [
[['uid', 'username'], ['key', 'configkey']],
[],
[['--default-value', false, true]],
true,
null,
],
'Call with uid and empty key with default-value option should fail check' => [
[['uid', 'username'], ['key', '']],
[],
[['--default-value', false, true]],
true,
'The "default-value" option can only be used when specifying a key.',
],
'Call with uid, key, value should pass check' => [
[['uid', 'username'], ['key', 'configkey'], ['value', '']],
[],
[],
true,
null,
],
'Call with uid, empty key and empty value should fail check' => [
[['uid', 'username'], ['key', ''], ['value', '']],
[],
[],
true,
'The value argument can only be used when specifying a key.',
],
'Call with uid, key, empty value and default-value option should fail check' => [
[['uid', 'username'], ['key', 'configkey'], ['value', '']],
[],
[['--default-value', false, true]],
true,
'The value argument can not be used together with "default-value".',
],
'Call with uid, key, empty value and update-only option should pass check' => [
[['uid', 'username'], ['key', 'configkey'], ['value', '']],
[['update-only', true]],
[],
true,
null,
],
'Call with uid, key, null value and update-only option should fail check' => [
[['uid', 'username'], ['key', 'configkey'], ['value', null]],
[['update-only', true]],
[],
true,
'The "update-only" option can only be used together with "value".',
],
'Call with uid, key and delete option should pass check' => [
[['uid', 'username'], ['key', 'configkey']],
[['delete', true]],
[],
true,
null,
],
'Call with uid, empty key and delete option should fail check' => [
[['uid', 'username'], ['key', '']],
[['delete', true]],
[],
true,
'The "delete" option can only be used when specifying a key.',
],
'Call with uid, key, delete option and default-value should fail check' => [
[['uid', 'username'], ['key', 'configkey']],
[['delete', true]],
[['--default-value', false, true]],
true,
'The "delete" option can not be used together with "default-value".',
],
'Call with uid, key, empty value and delete option should fail check' => [
[['uid', 'username'], ['key', 'configkey'], ['value', '']],
[['delete', true]],
[],
true,
'The "delete" option can not be used together with "value".',
],
'Call with uid, key, delete and error-if-not-exists should pass check' => [
[['uid', 'username'], ['key', 'configkey']],
[['delete', true], ['error-if-not-exists', true]],
[],
true,
null,
],
'Call with uid, key and error-if-not-exists should fail check' => [
[['uid', 'username'], ['key', 'configkey']],
[['delete', false], ['error-if-not-exists', true]],
[],
true,
'The "error-if-not-exists" option can only be used together with "delete".',
],
];
}
/**
* @dataProvider dataCheckInput
*/
public function testCheckInput(array $arguments, array $options, array $parameterOptions, bool $existingUser, ?string $expectedException): void {
$this->consoleInput->expects($this->any())
->method('getArgument')
->willReturnMap($arguments);
$this->consoleInput->expects($this->any())
->method('getOption')
->willReturnMap($options);
$this->consoleInput->expects($this->any())
->method('hasParameterOption')
->willReturnCallback(function (string|array $values, bool $onlyParams = false) use ($parameterOptions): bool {
$arguments = func_get_args();
foreach ($parameterOptions as $parameterOption) {
// check the arguments of the function, if they are the same, return the mocked value
if (array_diff($arguments, $parameterOption) === []) {
return end($parameterOption);
}
}
return false;
});
$returnedUser = null;
if ($existingUser) {
$mockUser = $this->createMock(IUser::class);
$mockUser->expects($this->once())->method('getUID')->willReturn('user');
$returnedUser = $mockUser;
}
$this->userManager->expects($this->once())
->method('get')
->willReturn($returnedUser);
$command = $this->getCommand();
try {
$this->invokePrivate($command, 'checkInput', [$this->consoleInput]);
$this->assertNull($expectedException);
} catch (\InvalidArgumentException $e) {
$this->assertEquals($expectedException, $e->getMessage());
}
}
public function testCheckInputExceptionCatch(): void {
$command = $this->getCommand(['checkInput']);
$command->expects($this->once())
->method('checkInput')
->willThrowException(new \InvalidArgumentException('test'));
$this->consoleOutput->expects($this->once())
->method('writeln')
->with('<error>test</error>');
$this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
public static function dataExecuteDeleteProfileProperty(): array {
return [
'Deleting existing property should succeed' => ['address', 'Berlin', false, null, Command::SUCCESS],
'Deleting existing property with error-if-not-exists should succeed' => ['address', 'Berlin', true, null, Command::SUCCESS],
'Deleting non-existing property should succeed' => ['address', '', false, null, Command::SUCCESS],
'Deleting non-existing property with error-if-not-exists should fail' => ['address', '', true, '<error>The property does not exist for user "username".</error>', Command::FAILURE],
];
}
/**
* Tests the deletion mechanism on profile settings.
*
* @dataProvider dataExecuteDeleteProfileProperty
*/
public function testExecuteDeleteProfileProperty(string $configKey, string $value, bool $errorIfNotExists, ?string $expectedLine, int $expectedReturn): void {
$uid = 'username';
$appName = 'profile';
$command = $this->getCommand([
'writeArrayInOutputFormat',
'checkInput',
]);
$this->consoleInput->expects($this->any())
->method('getArgument')
->willReturnMap([
['uid', $uid],
['app', $appName],
['key', $configKey],
]);
$mocks = $this->setupProfilePropertiesMock([$configKey => $value]);
$command->expects($this->once())
->method('checkInput')
->willReturn($mocks['userMock']);
$this->consoleInput->expects($this->atLeastOnce())
->method('hasParameterOption')
->willReturnMap([
['--delete', false, true],
['--error-if-not-exists', false, $errorIfNotExists],
]);
if ($expectedLine === null) {
$this->consoleOutput->expects($this->never())
->method('writeln');
$mocks['profilePropertiesMocks'][0]->expects($this->once())
->method('setValue')
->with('');
$this->accountManager->expects($this->once())
->method('updateAccount')
->with($mocks['accountMock']);
} else {
$this->consoleOutput->expects($this->once())
->method('writeln')
->with($expectedLine);
$this->accountManager->expects($this->never())
->method('updateAccount');
}
$this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
public function testExecuteSetProfileProperty(): void {
$command = $this->getCommand([
'writeArrayInOutputFormat',
'checkInput',
]);
$uid = 'username';
$propertyKey = 'address';
$propertyValue = 'Barcelona';
$this->consoleInput->expects($this->atLeast(3))
->method('getArgument')
->willReturnMap([
['uid', $uid],
['key', $propertyKey],
['value', $propertyValue],
]);
$mocks = $this->setupProfilePropertiesMock([$propertyKey => $propertyValue]);
$command->expects($this->once())
->method('checkInput')
->willReturn($mocks['userMock']);
$mocks['profilePropertiesMocks'][0]->expects($this->once())
->method('setValue')
->with($propertyValue);
$this->accountManager->expects($this->once())
->method('updateAccount')
->with($mocks['accountMock']);
$this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
public static function dataExecuteGet(): array {
return [
'Get property with set value should pass' => ['configkey', 'value', null, 'value', Command::SUCCESS],
'Get property with empty value and default-value option should pass' => ['configkey', '', 'default-value', 'default-value', Command::SUCCESS],
'Get property with empty value should fail' => ['configkey', '', null, '<error>The property does not exist for user "username".</error>', Command::FAILURE],
];
}
/**
* @dataProvider dataExecuteGet
*/
public function testExecuteGet(string $key, string $value, ?string $defaultValue, string $expectedLine, int $expectedReturn): void {
$command = $this->getCommand([
'writeArrayInOutputFormat',
'checkInput',
]);
$uid = 'username';
$this->consoleInput->expects($this->any())
->method('getArgument')
->willReturnMap([
['uid', $uid],
['key', $key],
]);
$mocks = $this->setupProfilePropertiesMock([$key => $value]);
$command->expects($this->once())
->method('checkInput')
->willReturn($mocks['userMock']);
if ($value === '') {
if ($defaultValue === null) {
$this->consoleInput->expects($this->atLeastOnce())
->method('hasParameterOption')
->willReturn(false);
} else {
$this->consoleInput->expects($this->atLeastOnce())
->method('hasParameterOption')
->willReturnCallback(fn (string|array $values): bool => $values === '--default-value');
$this->consoleInput->expects($this->once())
->method('getOption')
->with('default-value')
->willReturn($defaultValue);
}
}
$this->consoleOutput->expects($this->once())
->method('writeln')
->with($expectedLine);
$this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
public function testExecuteList(): void {
$uid = 'username';
$profileData = [
'pronouns' => 'they/them',
'address' => 'Berlin',
];
$command = $this->getCommand([
'writeArrayInOutputFormat',
'checkInput',
]);
$this->consoleInput->expects($this->any())
->method('getArgument')
->willReturnMap([
['uid', $uid],
['key', ''],
]);
$mocks = $this->setupProfilePropertiesMock(['address' => $profileData['address'], 'pronouns' => $profileData['pronouns']]);
$command->expects($this->once())
->method('checkInput')
->willReturn($mocks['userMock']);
$command->expects($this->once())
->method('writeArrayInOutputFormat')
->with($this->consoleInput, $this->consoleOutput, $profileData);
$this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
/**
* Helper to avoid boilerplate in tests in this file when mocking objects
* of IAccountProperty type.
*
* @param array<string, string> $properties the properties to be set up as key => value
* @return array{
* userMock: IUser&MockObject,
* accountMock: IAccount&MockObject,
* profilePropertiesMocks: IAccountProperty&MockObject[]
* }
*/
private function setupProfilePropertiesMock(array $properties): array {
$userMock = $this->createMock(IUser::class);
$accountMock = $this->createMock(IAccount::class);
$this->accountManager->expects($this->atLeastOnce())
->method('getAccount')
->with($userMock)
->willReturn($accountMock);
/** @var IAccountProperty&MockObject[] $propertiesMocks */
$propertiesMocks = [];
foreach ($properties as $key => $value) {
$propertiesMocks[] = $this->getAccountPropertyMock($key, $value);
}
if (count($properties) === 1) {
$accountMock->expects($this->atLeastOnce())
->method('getProperty')
->with(array_keys($properties)[0])
->willReturn($propertiesMocks[array_key_first($propertiesMocks)]);
} else {
$accountMock->expects($this->atLeastOnce())
->method('getAllProperties')
->willReturnCallback(function () use ($propertiesMocks) {
foreach ($propertiesMocks as $property) {
yield $property;
}
});
}
return [
'userMock' => $userMock,
'accountMock' => $accountMock,
'profilePropertiesMocks' => $propertiesMocks,
];
}
private function getAccountPropertyMock(string $name, string $value): IAccountProperty&MockObject {
$propertyMock = $this->getMockBuilder(IAccountProperty::class)
->disableOriginalConstructor()
->getMock();
$propertyMock->expects($this->any())
->method('getName')
->willReturn($name);
$propertyMock->expects($this->any())
->method('getValue')
->willReturn($value);
return $propertyMock;
}
}

@ -7,44 +7,31 @@
namespace Tests\Core\Command\User;
use InvalidArgumentException;
use OC\Core\Command\User\Setting;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUserManager;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Test\TestCase;
class SettingTest extends TestCase {
/** @var \OCP\IUserManager|\PHPUnit\Framework\MockObject\MockObject */
protected $userManager;
/** @var \OCP\IConfig|\PHPUnit\Framework\MockObject\MockObject */
protected $config;
/** @var \OCP\IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
protected $connection;
/** @var \Symfony\Component\Console\Input\InputInterface|\PHPUnit\Framework\MockObject\MockObject */
protected $consoleInput;
/** @var \Symfony\Component\Console\Output\OutputInterface|\PHPUnit\Framework\MockObject\MockObject */
protected $consoleOutput;
protected IUserManager&MockObject $userManager;
protected IConfig&MockObject $config;
protected IDBConnection&MockObject $connection;
protected InputInterface&MockObject $consoleInput;
protected MockObject&OutputInterface $consoleOutput;
protected function setUp(): void {
parent::setUp();
$this->userManager = $this->getMockBuilder(IUserManager::class)
->disableOriginalConstructor()
->getMock();
$this->config = $this->getMockBuilder(IConfig::class)
->disableOriginalConstructor()
->getMock();
$this->connection = $this->getMockBuilder(IDBConnection::class)
->disableOriginalConstructor()
->getMock();
$this->consoleInput = $this->getMockBuilder(InputInterface::class)
->disableOriginalConstructor()
->getMock();
$this->consoleOutput = $this->getMockBuilder(OutputInterface::class)
->disableOriginalConstructor()
->getMock();
$this->userManager = $this->createMock(IUserManager::class);
$this->config = $this->createMock(IConfig::class);
$this->connection = $this->createMock(IDBConnection::class);
$this->consoleInput = $this->createMock(InputInterface::class);
$this->consoleOutput = $this->createMock(OutputInterface::class);
}
public function getCommand(array $methods = []) {
@ -217,7 +204,7 @@ class SettingTest extends TestCase {
try {
$this->invokePrivate($command, 'checkInput', [$this->consoleInput]);
$this->assertFalse($expectedException);
} catch (\InvalidArgumentException $e) {
} catch (InvalidArgumentException $e) {
$this->assertEquals($expectedException, $e->getMessage());
}
}
@ -226,7 +213,7 @@ class SettingTest extends TestCase {
$command = $this->getCommand(['checkInput']);
$command->expects($this->once())
->method('checkInput')
->willThrowException(new \InvalidArgumentException('test'));
->willThrowException(new InvalidArgumentException('test'));
$this->consoleOutput->expects($this->once())
->method('writeln')