Why does dependecy injection use public methods?
Correct me if I'm wrong, but it's possible to change the implementation using reflexion.
DI is not a goal in itself. The purpose of DI is to enable loose coupling through favoring composition over inheritance, and that's only possible if you expose a public API for the purpose.
You can't recompose components in new and exiting ways without the public API.
That's a pretty blanket statement and isn't true. My preference is generally to use package-private constructors (or public constructors on package-private classes, since it doesn't matter then) for dependency injection since that allows you to instantiate and inject a class yourself (with no reflection or injector) for testing in a test class in the same package.
Keep in mind that the security policy may prevent one from calling protected, package private, or private methods even via the reflection API. If the DI framework is to work in all environments, then it can only rely on public methods.
Just to elaborate on the answer ColinD gave (I never even knew about package-private classes until a year of programming Java). With an app developed with a DI framework I believe you would make interfaces public and perhaps some abstract classes and Enums:
package org.my.service;
public interface Service {
public void process();
}
Then, the concrete implementation would be package-private (no public keyword)
package org.my.service;
class RealService {
public void process() {/*do something*/}
}
This enforces the concept of information hiding and means implementation details do not leak into the public API. It also means you cannot use the class outside of that package (compile-time error if you try -- you can't "new" it anywhere).
Again as ColinD said, you can unit test it because your unit test will reside in org.my.service.
DI frameworks have many ways to inject dependencies
constructor injection
setter injection
initializer injection
field injection
By using the first three, with modifier public you can set the dependencies manually even if the class is used outside a DI framework.
However, the 4th option is widely used. The most common scenario where you may need to manually set the dependencies are unit tests. For that spring, for example, offers ReflectionTestUtils, so that you can inject into fields with 1 line, and that is more or less fine.
Related
So I'm implementing a Dependency Injection framework into my Java project (Google Guice) and everything is pretty good, I like it but there's a small problem;
I want to make a static instance of my main project's class (where it instantiates the dependencies, etc). But I don't know any method to instantiate it using Guice, I can't instantiate it manually because I'm using DI in the constructor of it (I have objects in the constructor) which means that I am not able to access the class' non-static variables needed to instantiate the class.
I tried using a Provider but I couldn't really understand where to bind it, because I don't want to have an interface for the main class (will if needed).
If you are wanting to mix a static instance of a class with dependency injection, you have somewhat missed the point of dependency injection: you can simply inject the instance of the class.
If you want there to be a single instance of a class for your injector, bind it in #Singleton scope: either:
bind(YourClass.class).in(Singleton.class);
in your module's configure() method, or
#Provides #Singleton YourClass provideYourClassInstance() {
// ...
}
in your module, or
#Singleton class YourClass {
// ...
}
in the actual class declaration.
Then just inject this instance like any other:
class SomeOtherClass {
#Inject SomeOtherClass(YourClass instance) {
// ... Do something with instance, like assign it to a field.
}
}
The point is that SomeOtherClass shouldn't need know anything about the lifetime of instance: it simply doesn't matter whether this is a singleton instance, or every class using it has its own instance.
You can get three different answers here depending on the question.
To directly answer the question in the title (DI with arguments in the constructor), you can mix DI with constuctor arguments by instead injecting a Factory. Though you're welcome to write one manually, Guice can do this for you as assisted injection (see FactoryModuleBuilder), or you can use the equivalent code-generated solution AutoFactory popular through Dagger.
If you're trying to initialize a static class's fields in a Guice application, Guice can do that for you as soon as the Injector is created. Simply call requestStaticInjection in a Module you feed to Guice. This, as Andy Turner pointed out, will cause you to miss out on some of the benefits of Guice: Because you're injecting the instance statically, there's very little opportunity for you to provide replacement implementations in tests or in other class reuse. Guice describes this more in the static injections section of its wiki:
When migrating an application from static factories to Guice, it is possible to change incrementally. Static injection is a helpful crutch here. It makes it possible for objects to partially participate in dependency injection, by gaining access to injected types without being injected themselves. [...]
Static members will not be injected at instance-injection time. This API is not recommended for general use because it suffers many of the same problems as static factories: it's clumsy to test, it makes dependencies opaque, and it relies on global state.
The best overall solution is in Andy's answer: Adapt your application to use DI, which will let it inject the objects that you would otherwise make static.
This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 5 years ago.
Who has a solution for that common need.
I have a class in my application.
some methods are public, as they are part of the api,
and some are private, as they for internal use of making the internal flow more readable
now, say I want to write a unit test, or more like an integration test, which will be located in a different package, which will be allowed to call this method, BUT, I want that normal calling to this method will not be allowed if you try to call it from classes of the application itself
so, I was thinking about something like that
public class MyClass {
public void somePublicMethod() {
....
}
#PublicForTests
private void somePrivateMethod() {
....
}
}
The annotation above will mark the private method as "public for tests"
which means, that compilation and runtime will be allowed for any class which is under the test... package , while compilation and\or runtime will fail for any class which is not under the test package.
any thoughts?
is there an annotation like this?
is there a better way to do this?
it seems that the more unit tests you write, to more your inforced to break your encapsulation...
The common way is to make the private method protected or package-private and to put the unit test for this method in the same package as the class under test.
Guava has a #VisibleForTesting annotation, but it's only for documentation purposes.
If your test coverage is good on all the public method inside the tested class, the privates methods called by the public one will be automatically tested since you will assert all the possible case.
The JUnit Doc says:
Testing private methods may be an indication that those methods should be moved into another class to promote reusability.
But if you must...
If you are using JDK 1.3 or higher, you can use reflection to subvert the access control mechanism with the aid of the PrivilegedAccessor. For details on how to use it, read this article.
Consider using interfaces to expose the API methods, using factories or DI to publish the objects so the consumers know them only by the interface. The interface describes the published API. That way you can make whatever you want public on the implementation objects and the consumers of them see only those methods exposed through the interface.
dp4j has what you need. Essentially all you have to do is add dp4j to your classpath and whenever a method annotated with #Test (JUnit's annotation) calls a method that's private it will work (dp4j will inject the required reflection at compile-time). You may also use dp4j's #TestPrivates annotation to be more explicit.
If you insist on also annotating your private methods you may use Google's #VisibleForTesting annotation.
An article on Testing Private Methods lays out some approaches to testing private code. using reflection puts extra burden on the programmer to remember if refactoring is done, the strings aren't automatically changed, but I think it's the cleanest approach.
Or you can extract this method to some strategy object. In this case you can easily test extracted class and don't make method public or some magic with reflection/bytecode.
Okay, so here we have two things that are being mixed. First thing, is when you need to mark something to be used only on test, which I agree with #JB Nizet, using the guava annotation would be good.
A different thing, is to test private methods. Why should you test private methods from the outside? I mean.. You should be able to test the object by their public methods, and at the end that its behavior. At least, that we are doing and trying to teach to junior developers, that always try to test private methods (as a good practice).
I am not aware of any such annotation, however the following may be of value: unit testing private methods
or the following: JMockit
You can't do this, since then how could you even compile your tests? The compiler won't take the annotation into account.
There are two general approaches to this
The first is to use reflection to access the methods anyway
The second is to use package-private instead of private, then have your tests in the same package (but in a different module). They will essentially be private to other code, but your tests will still be able to access them.
Of course, if you do black-box testing, you shouldn't be accessing the private members anyway.
We recently released a library that helps a lot to access private fields, methods and inner classes through reflection : BoundBox
For a class like
public class Outer {
private static class Inner {
private int foo() {return 2;}
}
}
It provides a syntax like :
Outer outer = new Outer();
Object inner = BoundBoxOfOuter.boundBox_new_Inner();
new BoundBoxOfOuter.BoundBoxOfInner(inner).foo();
The only thing you have to do to create the BoundBox class is to write #BoundBox(boundClass=Outer.class) and the BoundBoxOfOuter class will be instantly generated.
As much as I know there is no annotation like this. The best way is to use reflection as some of the others suggested. Look at this post:
How do I test a class that has private methods, fields or inner classes?
You should only watch out on testing the exception outcome of the method. For example: if u expect an IllegalArgumentException, but instead you'll get "null" (Class:java.lang.reflect.InvocationTargetException).
A colegue of mine proposed using the powermock framework for these situations, but I haven't tested it yet, so no idea what exactly it can do. Although I have used the Mockito framework that it is based upon and thats a good framework too (but I think doesn't solve the private method exception issue).
It's a great idea though having the #PublicForTests annotation.
Cheers!
I just put the test in the class itself by making it an inner class:
https://rogerkeays.com/how-to-unit-test-private-methods
I am new to spring Mvc and in a lot of tutorials, I found there is a Dao interface like this
public interface StudentDAO {
public List<Student> getStudents();
public void addEntry(Student student);
public void updateEntry(Student student);
public void deleteEntry(Student student);
public Student getStudentById(int id);
}
and also services like this
public interface StudentService {
public List<Student> getStudents();
public void addEntry(Student student);
public void updateEntry(Student student);
public void deleteEntry(Student student);
public Student getStudentById(int id);
}
And there are implementations for these interfaces.
My question is why we need interfaces rather than direct implementation classes?
I'm glad to see someone questioning that practice.
Spring Framework introduced long time ago the pattern of defining interfaces for their managed service / DAO beans. I think that practice was introduced due to limitations in the technology they used to create dynamic proxies.
When a Spring-managed bean is defined, the framework creates a proxy to the underlying instance with the purpose of decorating it with cross-cutting functionality using AOP techniques. Apparently, the tools they used to implement those proxies in the early versions of Spring Famework required an interface to create the proxy out of it.
This requirement no longer holds in the latest versions of Spring Framework and you're safe to dispose of those useless interfaces.
The reason for ease of testing does not hold nowadays, either, as mocking frameworks like Mockito are also capable of mocking concrete classes.
In addition, you can use the #Primary annotation to replace the real implementation with a custom mock in a testing context.
For those reasons, I would scrap interfaces for internal service and DAO classes that will never have multiple co-existing valid implementations.
Keep interfaces for design patterns that really need them.
In theory, it creates interfaces to decrease the coupling. In other words you create interfaces that are the communication contracts. And with that you can have more of an implementation for the same contract. Example: In PersonDao you can have implementation with hibernate and one with native SQL. With that in places where you used, you only inject interace and CDI itself solves the implementation, then you easily change the implementation without affecting the places where it is used interfaces.
In practice in my projects, depending on the situation, do not create the interfaces, but I will emphasize, it depends on the project. Example: A DAO in the majority of the time it never changed its implementation, that is, I see no need to create the interfaces in these cases directly implement the concrete classes.
The post Jiri Tousek is an example for the use of interfaces. However in my tests, I always use the complete flow, including the database.
Perhaps the simplest concrete illustration for the need is testing.
With the DAO interface, you can test your application's logic without the need to have a DB running that's accessible from the machine running tests, simply by swapping your DAO implementation for a dummy one during tests. That dummy implementation can then provide consistent data for tests that doesn't change between test runs, cannot be overwritten in DB by accident, is versioned in you Git/SVN/whatever etc.
In general, this is part of the Program to an interface, not an implementation design principle.
In my experience, this separation of interface vs. implementation is a good idea even if you're never going to have multiple implementations, because it encourages programmers to think more deeply about the contract of the class.
Note that the principle is not universally accepted, here are some counter-arguments for example.
if you are doing project it includes some database so you must define function in interface in this way Which you use is easily seen.
This is a slightly esoteric questions about how public to make constructors when using an IoC container. I'm using java, Guice and Junit4, but I'm sure this question is more general.
Under Best Practices in the Guice docs, it says "Keep constructors as hidden as possible". This is something I quite agree with, so I was happy to go ahead a make my constructors private and rely on Guice for instantiation.
However, this brings up an issue with mocking classes and unit testing. If all my constructors are private, then how can I instantiate something in a unit test and pass in a mocked dependency? Having to create a new Guice module for every unit test seems like overkill to me. Surely, I must therefore actually make those constructors public.
Which brings me to the question: Given that DI is so useful when combined with unit testing, is the best practices in the Guice docs about keeping constructors hidden actually a mistake?.
Read further in the same document, which suggests giving the constructors default access. Then put your unit tests in the same package.
Default access is provided if none of public, protected or private are specified.
From the document you referenced:
As a correction, simply limit the visibility of both your implementation classes, and their constructors. Typically package private is preferred for both, as this facilitates:
binding the class within a Module in the same package
unit testing the class through means of direct instantiation
Specifically, I am using a Singleton model using an enum. I have an enum singleton service (business logic) calling into an enum singleton dao. I would like to do write unit tests for my service but I can not mock my enum dao because, well, it's an enum and final. Yes, I saw the article about doing it with reflection, but I'd rather avoid that if possible.
So my thought was this, why not add another value TEST_INSTANCE to my enum? (And that really is the core question.)
public enum MyDao {
INSTANCE,
TEST_INSTANCE;
public boolean methodIWouldMockIfICould()
{
if(this == TEST_INSTANCE) { return true; }
... //method code here
}
}
Trying this seems to work initially, but I'm hesitant.
This has a bad smell to me.
Assuming the code deployed to my web application uses only INSTANCE and that the only place TEST_INSTANCE is ever used is in tests, will this enum still follow the singleton model?
Is there anything else bad about this that I am not considering?
Thank you much in advance,
-Matt
Edit I would love to use Spring for DI, but I am not allowed to. Legacy system and the higher ups have simply said "no, not yet." I have hopes that it will come, but I'm not allowed to yet, so this is my solution effort in the meantime.
I wouldn't bother to enforce the singleton pattern in your code using an Enum. Instead, just create a DAO interface and a corresponding concrete implementation.
In your unit tests, mock your DAO interface. In your production code, use dependency injection (DI) to stuff your concrete implementation into your other classes. Most DI frameworks will allow you to enforce the singleton property via configuration settings.