-
Notifications
You must be signed in to change notification settings - Fork 1k
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
DependencyInjection Tests? #942
Comments
Yes, we should absolutely add some. @Danthar, @jcwrequests, @nvivo - do any of you have interest in working on this? If so, how can we best support you? |
@Aaronontheweb I can certainly pitch in. My only thing is do you have any documentation on what testing framework you use and does this need to follow the Akka Testkit and if so what documentation do you have on best practices doing so. |
@rogeralsing @Aaronontheweb The reason I asked my question is that all Akka tests are around a spec convention using xunit. Is this a requirement? Do you have any guidelines? Should the tests be located with the contrib code? What specs do you want and test for? @Danthar @nvivo I am more then willing to pitch in just let me know where I can help. |
Great questions @jcwrequests!
|
@Aaronontheweb I guess I could look at the Props spec and go from there since they are closely related. |
If you google on akka testkit you will find some blog posts by @HCanber explaining some stuff about the testkit. I found them to be a great intro if you need one. -----Original Message----- @Aaronontheweb I guess I could look at the Props spec and go from there since they are closely related. |
We should port this http://doc.akka.io/docs/akka/snapshot/scala/testing.html |
BTW. regarding tests for DI. we should totally do a spec for DI and then let different DI impls inherit that and run the same tests using the same types and actors. To verify that each impl behaves the same way. |
@rogeralsing I agree. Where do we begin? |
@Danthar Thanks I found the post. @rogeralsing @Aaronontheweb I will proceed with coming up with a DIExt Core test project and put it under contrib along with all the rest of the DI stuff. As I commit stuff to my personal repo I will link back here for feedback. |
I have added a new project on my repo and will start getting it all setup tonight. |
Just documented Aaron's comments from gitter |
Here is a link https://github.com/jcwrequests/akka.net/tree/DI-Core-Testing/src/contrib/dependencyInjection/Tests/Akka.DI.Core.Tests |
For spec idea's. I think it could be really simple. The DI integration only goes as deep as the Props object. So that means if you have that down. You don't need to write specs for all the various Actor invariants as they will be covered by existing tests. |
@Danthar there is a bit more to it e.g. when actor terminates it can callback to the container to dispose/release dependencies with different lifecycle managers. |
Ah your right. The DIActorProducer does let the DI container instantiate the actor and also calls Release. But even then all of Akka's initialisation is based on the type definition in the Props instance. So if you verify that a correct Props instance is created you still have alot of scenario's covered. Right? |
@nvivo @Danthar @akkadotnet/owners So how do you want and spec this out? Has anyone had a chance to check out my shell project just to be sure at least from a reference point of view everything is correct? I will see what I can come up with and just add it to the project. Just send me private gitter messages with any questions. Cheers. |
Project structure looks good to me. However I would drop the |
@Danthar Thanks. I had a few moments just now at lunch and made the changes. |
@nvivo @Danthar @akkadotnet/owners I have continued with project. Went through some strange issues with building the project with XUnit and the old Xunit test runner but got that resolved. I also started adding some test cases. Until I get more feedback I will at least implement all of the prop tests then move onto to some of the things @Aaronontheweb was saying. @rogeralsing I have not had a chance to look at http://doc.akka.io/docs/akka/snapshot/scala/testing.html but it's on my todo. I looking forward to the feedback and getting this done PR done. |
I found something interesting and am not sure if it's worth extending DI for this case but I will leave it you guys. Here is the example:
Thanks. |
As we discussed previously, I don't like the current API of DI, it's one of those places where it would be a good idea to diverge from jvm, so I don't have much to say about which scenarios it should be tested against. I see the benefit from that proposal in that currently its quite hard to use DI and add settings to props. The requirement of explicitly calling the PropsResolver sometimes makes it a pain to use. But that PR #966 seems to just mask the issue a little bit. IMO, the solution should be to get rid of the DI() extension and allow the existing api of Props and ActorOf to take advantage of DI in a transparent way, so we don't need to duplicate all the api. |
I'll do a full review of this on Thursday / Friday. Don't have time to give this the attention it deserves until then. |
You said 2 things here that caught my attention:
This only makes sense is if you don't want to use DI. When you use DI, you can't make it the exception and use it rarely, it just doesn't work that way. And this is the problem with the current API in my opinion, it's made by people that don't like DI in a way to make it painful to use. The issue is not typing 4 extra characters, but the fact that you have to decide when you need it or not. If I have some code with The only way this change is reasonable is if you don't actually use DI and think of it as a helper you call sometimes when you don't want to type much - that's not the idea. The whole idea of DI is to avoid changes in application code when dependencies change. The solution you said yourself:
So, if it's all about creating Props, what I end up doing is to have my own Props factory that abstract the decision in a way that makes sense:
This way I have a single API to code for and I never have to change application code if I add dependencies. This is not forcing DI anywhere, and is not affecting remote deployment in any way - because I can still create props manually if I need to. DI is used only when I don't specify parameters to Props, which makes it clear in code I don't care about dependencies. And if I want all my props to be remote deployable, a different producer can be used that always produce serializable props. I'm not saying this is perfect, but beats the hell out of the current API and makes it usable in real world. |
The impression I get from pondering this discussion is that we are conflating two things that should rather be kept separate: creating an Actor means spawning a new isolated and possibly distributed independent agent of computation, this act is about delegating responsibility. The parent Actor’s intention and responsibility is to define exactly the task that is to be delegated. If it so happens that the execution of the task requires a dependency that is independent of the parent—meaning that the parent does not or cannot care about the details of this dependency—then it would be best to keep this dependency completely out of the Actor creation, i.e. to keep it out of the Props. The exemplary database connection has no business in the Actor infrastructure if its selection is not the parent’s responsibility, instead the constructor of the Actor should perform the necessary lookups to obtain all dependencies before beginning to perform its designated function. This thought was triggered by @nvivo’s remark that the invocation sites of Is a solution conceivable that completely hides the dependencies within the Actor such that the parent (and Akka) does not need to know about them at all? Concretely, I’m thinking of using the DI extension within PreStart to obtain either the individual dependencies or to have a small (and shallow) dependency container object be injected by the DI framework. This would leave the orthogonal concerns of “unit of computation” (Actor) and “managed dependencies” unentangled and unencumbered by each other. In other words, I see no reason why the Actor instance also needs to be the business logic instance; as so often, it seems favorable to prefer composition over inheritance. |
I agree with Natan. If my memory serves me correctly NServiceBus handled the problem the same way as Natan suggests. At least in the open source version. Still I would recommend talking to Mark Seemann if I had a twitter account I would do it myself. Sorry for being annoying about that but he did write the book. :) https://github.com/Particular/NServiceBus/tree/develop/src/NServiceBus.Core/ObjectBuilder |
@rkuhn, If I understand you correctly, you mean that since the only parameters in an actor constructor should be the ones related to the task it needs to accomplish, and the parent MUST know exactly which task the child should perform, then And in that case, there would be no place for DI to create Props. That raises the question on why do the current DI extensions do exactly that? You made good points about separation of concerns. Maybe you can enlighten me, but I don't see how could this be enforced using the semantics you described. Separating what is a "dependency of the code" and a "dependency of the task that code should perform" is quite hard to tell and the answer will in most cases be blurry. Another thing that concerns me is that constructor injection is a well known and well supported pattern, it works fine. Diverging from it in favor of a service locator in PreStart would confuse a lot of people, and the only benefit would be some "sense of accomplishment" at the cost of flexibility and control.
I think so. I'm achieving this today by separating concerns this way:
So, whenever I need DI, it's always hidden. When I don't need it, I just don't use it. To me this works fine today, with the exception that I have to ignore the official DI methods and roll my own which bothers me a little bit but doesn't hurt me. I like the idea of separating concerns, and I'd support moves to improve DI. I just I don't know if exposing the DI kernel on PreStart would be a good thing. Maybe some of the interested folks like @jcwrequests, @Danthar and @thomaslazar can post their opinions. |
I agree with this in concept, but in practice I think this is more of an aspirational standard. When a parent provides constructor arguments to the That way I've personally used DI for database connections is as you describe - I resolve them using the DI container inside the actor's
Practically speaking, I could see people being resistant to this because it's different than how most .NET developers consume DI containers today. Constructor injection is the typical way of doing it and has the added benefit of being easier to test (you don't need to "mock" a DI container as part of your tests this way.)
This hasn't been true in my experience; Akka.NET is fundamentally different from ASP.NET MVC / NancyFX in the sense that you're directly responsible for creating DI-ed objects in Akka.NET, whereas a factory does it for you on invocation in those other contexts. There's nothing about the DI or IoC patterns, AFAIK, that requires containers usage to be an invisible detail of the calling system. I actually like the way you made DI transparent inside That's why I think we're kind of stuck using an extension method or a factory to make it explicit. Unless we added the The way Akka.Remote and Akka.Cluster achieve their transparent actor creation changes is through overriding the |
That is basically the same conclusion I came to as well. Nothing is perfect and you will never be able to please everyone.The way it currently works is a very practical. Perhaps it might be interesting to create an experimental Akka for testing new ideas like having DI be a core principal. Again I know everyone is busy but it could be interesting. |
@jcwrequests one thing if we are making some changes that I really dislike at the moment and that confused me the other day. In the constructor for say the AutofacDependencyResolver we wire up the DI extension, so my initial config looked like:
Looking at the doco I did not see much mention of setting the resolver, and when I went digging I realized that what I was doing is not really required but you could instead do something like:
Could just be me but that just reads and feels strange, what would we think of the ability to just call a static Init method that could wire up the resolver:
Just "feels" nicer to me, feel free to throw the suggestion away :). Cheers |
I think it's more than the syntax of creating the dependency resolver. Currently, the way to use DI is:
The real issue to me is that the DI system has nothing to do with the ActorSystem or with the actor context, but is tied there for reasons that are no longer valid. If Props can be created independently of actor systems and a Props instance can used with any actor system, the whole idea that DI should be an actor system extension should be reexamined. |
Ok some updates, I have pushed a bunch of PRs to @Aaronontheweb fork that fixes our issues, what was done for the various containers:
It looks like what we should do is update the documentation for Windsor to warn about registering using a transient lifetime, and perhaps add some info the the Unity documentation. It looks like Windsor, Structuremap and NInject should just work as expected with happy defaults. Cheers |
@stefanedich Nice! |
I'll leave this and #1139 open for a bit to entertain the discussion around getting DI as it is right now to work as expected and to get clear on what those expectations are for the next couple of days. Spent some time with @nvivo today discussing some possible options for making DI more transparent in Akka.NET in the future, which would require something much more radical than what's currently being proposed. Any additional discussions about that should be moved to a new thread. The immediate goal of #1139 is just to spell out the assumptions we make about using DI in the context of actors and to test each implementation against those assumptions with the future benefit of regression testing. TL;DR; I just wanted to improve test coverage and behavioral consistency for DI in the short run, and we should be pushing the bug fixes and recommended container configuration settings out there with great haste. |
Akka.NET Dependency Injection testkit for #942
For those playing at home I just merged in the PR that gets all of @Aaronontheweb DI tests passing, my next goal is to update the DI documentation spelling out a few things for the various containers that require specific configuration when registering actors and add some more information to help anyone starting out with Akka.Net and DI to ensure they have the smoothest possible experience. |
@Aaronontheweb, is there a specific issue you will create to discuss the DI stuff, or can I create one? |
@nvivo I think we should have a discussion issue around how to make DI more transparent. including the stuff you and I talked about on Skype (maybe merging Akka.DI.Core into the main assembly.) |
cc @stefansedich still planning on documenting all of the recommending scoping / config options for each DI container in our docs? Once that's done we can close this issue out. |
Did this a long time ago, and moved everything out of the core repo. |
Don't we have any tests for the dependency injection parts?
if not, we should make some asap.
Related #941
Seems like there might be some conflicts between stashing and DI plugins.
The text was updated successfully, but these errors were encountered: