mtedone / podam

PODAM - POjo DAta Mocker
https://mtedone.github.io/podam
MIT License
323 stars 750 forks source link

Allow to map type manufacturers to indirectly inherited interfaces #220

Closed devshorts closed 7 years ago

devshorts commented 7 years ago

Hi, I'd like to be able to hook into the creation of objects (both with generic args and not) without leveraging annotation providers. Many of my classes need to be distributed and I don't want to add a public dependency on a testing lib.

As it stands I can't seem to figure out how to hook into the creation and population of classes. A good example here is I work in scala and I'd like to be able to customize how a List[String] is created, however the type args map that has both pieces of information is hidden away and isn't delegated to any custom type factories that I can register.

Another example I've found is that when you go to directly create a string outside of an object, it's always empty. You can hack around it by subclassing the get memoized object in the data strategy provider, but it'd be better to just delegate all creation to another provider

Is there a way to accomplish this?

daivanov commented 7 years ago

Hi,

I'd like to be able to customize how a List[String] is created

Then you should create your own version of CollectionTypeManufacturerImpl and register it to your DataProviderStrategy.

Another example I've found is that when you go to directly create a string outside of an object, it's always empty.

There is a test checking that a created string is not empty and it doesn't fail.

Hope this answers your questions.

devshorts commented 7 years ago

Very helpful. I see that the issue was fixed in the 7 release, as I was using the 6.0.1. I like all the new changes! No more spring is nice :)

Anyways, when creating a type manufacturer is there a way to get a reference back to the factory to be able to create elements of the collection? The CollectionTypeManufacturerImpl example only seems to create empty versions of those collections. Where would I create code to populate the built collections?

Edit: I can see there is a special private function called fillCollection in PodamFactoryImpl. Is there a way to delegate the collection.add(x)? Basically building scala collections do not follow the same semantics as java collections. I feel like I could create a type manufacturer that has a reference to the factory and fill the collection when I create it, but that seems hacky

devshorts commented 7 years ago

Ok, so that seems to work, however finding the type manufacutrer only walks the current supertype heirarchy and doesnt follow interfaces that extend other interaces.

For example, if I have a type manufacturer for

interface IFoo

and I have a class that is

class Bar extends IBar, IBiz

interface IBar extends IBaz
interface IBiz extends IFoo

Then the type manufacturer doesn't seem to find it

daivanov commented 7 years ago

Finding a matching manufacturer is tied with a task of inheritance tree traversal, which has no unique solution. What is a practical reason you cannot register manufacturer for type IBiz?

devshorts commented 7 years ago

why would it have no unique solution? Its a directed graph that can be walked.

Anyways, I did end up registering my manufacuterer, but i ended up having to create many small manufactureres for specific interfaces, vs one overarching one that is the root collection node of the scala tree and doing the conversions in the one matcher. the latter is much more flexible. It's not a huge deal, but I wanted to bring it up.

Thanks again!

devshorts commented 7 years ago

@daivanov I appreciate the help, I'll close this issue as I was able to accomplish all that I needed to. Thanks

daivanov commented 7 years ago

why would it have no unique solution? Its a directed graph that can be walked.

Because a walk is a linear procedure and a tree isn't a linear structure.

For example, after the recent change, if you register IBaz and IFoo manufacturers the former will be selected and this is not what you want.

devshorts commented 7 years ago

I see, yes you are right. However as long as you use a consistent graph walk (dfs/bfs) someone can consistently prioritize the ordering of the mappers right?

On Nov 1, 2016, at 11:32 PM, Daniil Ivanov notifications@github.com wrote:

why would it have no unique solution? Its a directed graph that can be walked. Because a walk is a linear procedure and a tree isn't linear structure.

For example, after the recent change, if you register IBaz and IFoo manufacturers the former will be selected and this is not what you want.

― You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub, or mute the thread.

daivanov commented 7 years ago

The only way to go around this problem is to register a manufacturer for the class Bar, which you reported as an original problem. Anyone who registers lots of manufacturers for interfaces will face this problem eventually.