Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QUESTION : Asserting complete mapping #86

Open
brendanjerwin opened this issue Apr 9, 2024 · 1 comment
Open

QUESTION : Asserting complete mapping #86

brendanjerwin opened this issue Apr 9, 2024 · 1 comment
Labels

Comments

@brendanjerwin
Copy link

A feature of the dotnet AutoMapper is AssertConfigurationIsValid() which will barf if a new property was added that was not able to be automagically mapped.

I'm trying to find a way to assert the same here. A unit test that will fail if there is a destination or source property that doesn't have an operation.

How might I go about this? Am I missing something obvious already?

@mark-gerarts
Copy link
Owner

Hi @brendanjerwin, this is a good question. It is not part of the library right now.

Do you want every property to have an explicit operation defined, or is it also considered valid if mapping is possible with the default operation (i.e. mapping properties with the same name)? If the former, you could hack it in yourself using a bit of reflection:

<?php

require 'vendor/autoload.php';

use AutoMapperPlus\Configuration\AutoMapperConfig;
use AutoMapperPlus\AutoMapper;
use AutoMapperPlus\MappingOperation\Operation;
use AutoMapperPlus\Configuration\MappingInterface;
use AutoMapperPlus\MappingOperation\DefaultMappingOperation;

class CustomConfig extends AutoMapperConfig
{
    private $configuredMappings = [];

    public function registerMapping(
        string $sourceClassName,
        string $destinationClassName
    ): MappingInterface {
        $this->configuredMappings[] = [$sourceClassName, $destinationClassName];
        return parent::registerMapping($sourceClassName, $destinationClassName);
    }

    public function assertValid(): void {
        foreach ($this->configuredMappings as [$sourceClassName, $destinationClassName]) {
            $mapping = $this->getMappingFor($sourceClassName, $destinationClassName);

            $sourceObject = (new \ReflectionClass($sourceClassName))->newInstance();
            $destinationObject = (new \ReflectionClass($destinationClassName))->newInstance();

            $properties = $mapping->getTargetProperties($destinationObject, $sourceObject);
            foreach ($properties as $property) {
                $operation = $mapping->getMappingOperationFor($property);
                if ($operation instanceof DefaultMappingOperation) {
                    throw new \Exception("${destinationClassName}::${property} has no explicit mapping operation defined");
                }
            }
        }
    }
}

class ClassA
{
    public $prop1 = 'property 1';
    public $prop2 = 'property 2';
}

class ClassB
{
    public $prop1;
    public $prop2;
}

$config = new CustomConfig();
$config
    ->registerMapping(ClassA::class, ClassB::class)
    ->forMember('prop1', Operation::setTo('hardcoded prop'));
$mapper = new AutoMapper($config);

$config->assertValid();

The latter can also be done with some additions to the code above. I call it hacking, since the public API of the library doesn't expose which mappings are actually registered.

If fleshed out a bit, it could be a good feature to actually implement in the library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants