How to re-initialize my bean - java

I have a bean in my applicationContext-test.xml that I use for mocking an external search engine. This way, when I run tests, any time my application code refers to this search engine, I know that I am using my mock engine instead of the real one.
A problem I am facing is that I want this engine to behave differently in different scenarios. For example, when I call getDocuments(), I usually want it to return documents. But sometimes I want it to throw an exception to make sure that my application code is handling the exception appropriately.
I can achieve this by referencing the bean in my test code and changing some stubs, but then I have to change the stubs back to what they were so that my other tests will also pass. This seems like bad practice for many reasons, so I'm seeking alternatives.
One alternative I considered was to reinitialize the bean completely. The bean is initialized from the applicationContext-test.xml with a static factory method. What I want to do is:
Reference the bean from my test code to change some of its stubs
Run the test using these new stubs
At the end of this test, reinitialize the bean using the static factory method specified in applicationContext-test.xml
I tried something like this:
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] { "applicationContext-test.xml" });
Factory factory = appContext.getBean(Factory.class);
factory = EngineMocks.createMockEngineFactory();
But this does not do the trick. Any tests that are run after this will still fail. It seems that my new factory variable contains the Factory that I want and behaves accordingly, but when the bean is referenced elsewhere, getDocuments() still throws the exception that was stubbed in previously. Clearly, my re-initialization only affected the local variable and not the bean itself.
Can someone tell me how I can accomplish my goal?
Update
While I appreciate suggestions as to how to write better tests and better mocks, my goal is to reinitialize a bean. I believe there is value in learning how to do this whether it fits my use case or not (I believe it does fit my use case, but I'm having a hard time convincing some of my critics here).
The only answers that will get any up votes or green ticks from me are those which suggest how I can reinitialize my bean.

You should define the cases when you want a result and the cases when you want an exception. They should be differentiated by input parameters to the method. Otherwise it is not a good test. So, for a given set of parameters the output should be predictable.

How about injecting different implementations of the search engine? Just create more beans representing the different mocks of the search engine.
one test class is initialized with one mock and another test class with another mock; this, of course, means you'll have more test classes for a certain class that you are testing (not that good/clean)
or...
inject more mocks (of the search engine) in 1 testing class. some testing methods (from that testing class) use one mock, other testing methods use another mock

Instead of:
factory = EngineMocks.createMockEngineFactory();
do:
factory.callMethodThatChangesTheStateOfThisObjectSuchThatItIsSuitableForYourTest(withOptionalParameters);
Also, if you are using Spring Integration Testing, make sure to annotate your method with #DirtiesContext so it won't affect the next test.

Related

Why is Spring's ApplicationContext.getBean with Interface considered bad? [duplicate]

I asked a general Spring question: Auto-cast Spring Beans and had multiple people respond that calling Spring's ApplicationContext.getBean() should be avoided as much as possible. Why is that?
How else should I gain access to the beans I configured Spring to create?
I'm using Spring in a non-web application and had planned on accessing a shared ApplicationContext object as described by LiorH.
Amendment
I accept the answer below, but here's an alternate take by Martin Fowler who discusses the merits of Dependency Injection vs. using a Service Locator (which is essentially the same as calling a wrapped ApplicationContext.getBean()).
In part, Fowler states, "With service locator the application class asks for it [the service] explicitly by a message to the locator. With injection there is no explicit request, the service appears in the application class - hence the inversion of control.
Inversion of control is a common feature of frameworks, but it's something that comes at a price. It tends to be hard to understand and leads to problems when you are trying to debug. So on the whole I prefer to avoid it [Inversion of Control] unless I need it. This isn't to say it's a bad thing, just that I think it needs to justify itself over the more straightforward alternative."
I mentioned this in a comment on the other question, but the whole idea of Inversion of Control is to have none of your classes know or care how they get the objects they depend on. This makes it easy to change what type of implementation of a given dependency you use at any time. It also makes the classes easy to test, as you can provide mock implementations of dependencies. Finally, it makes the classes simpler and more focused on their core responsibility.
Calling ApplicationContext.getBean() is not Inversion of Control! While it's still easy to change what implemenation is configured for the given bean name, the class now relies directly on Spring to provide that dependency and can't get it any other way. You can't just make your own mock implementation in a test class and pass that to it yourself. This basically defeats Spring's purpose as a dependency injection container.
Everywhere you want to say:
MyClass myClass = applicationContext.getBean("myClass");
you should instead, for example, declare a method:
public void setMyClass(MyClass myClass) {
this.myClass = myClass;
}
And then in your configuration:
<bean id="myClass" class="MyClass">...</bean>
<bean id="myOtherClass" class="MyOtherClass">
<property name="myClass" ref="myClass"/>
</bean>
Spring will then automatically inject myClass into myOtherClass.
Declare everything in this way, and at the root of it all have something like:
<bean id="myApplication" class="MyApplication">
<property name="myCentralClass" ref="myCentralClass"/>
<property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>
MyApplication is the most central class, and depends at least indirectly on every other service in your program. When bootstrapping, in your main method, you can call applicationContext.getBean("myApplication") but you should not need to call getBean() anywhere else!
Reasons to prefer Service Locator over Inversion of Control (IoC) are:
Service Locator is much, much easier for other people to following in your code. IoC is 'magic' but maintenance programmers must understand your convoluted Spring configurations and all the myriad of locations to figure out how you wired your objects.
IoC is terrible for debugging configuration problems. In certain classes of applications the application will not start when misconfigured and you may not get a chance to step through what is going on with a debugger.
IoC is primarily XML based (Annotations improve things but there is still a lot of XML out there). That means developers can't work on your program unless they know all the magic tags defined by Spring. It is not good enough to know Java anymore. This hinders less experience programmers (ie. it is actually poor design to use a more complicated solution when a simpler solution, such as Service Locator, will fulfill the same requirements). Plus, support for diagnosing XML problems is far weaker than support for Java problems.
Dependency injection is more suited to larger programs. Most of the time the additional complexity is not worth it.
Often Spring is used in case you "might want to change the implementation later". There are other ways of achieving this without the complexity of Spring IoC.
For web applications (Java EE WARs) the Spring context is effectively bound at compile time (unless you want operators to grub around the context in the exploded war). You can make Spring use property files, but with servlets property files will need to be at a pre-determined location, which means you can't deploy multiple servlets of the same time on the same box. You can use Spring with JNDI to change properties at servlet startup time, but if you are using JNDI for administrator-modifiable parameters the need for Spring itself lessens (since JNDI is effectively a Service Locator).
With Spring you can lose program Control if Spring is dispatching to your methods. This is convenient and works for many types of applications, but not all. You may need to control program flow when you need to create tasks (threads etc) during initialization or need modifiable resources that Spring didn't know about when the content was bound to your WAR.
Spring is very good for transaction management and has some advantages. It is just that IoC can be over-engineering in many situations and introduce unwarranted complexity for maintainers. Do not automatically use IoC without thinking of ways of not using it first.
It's true that including the class in application-context.xml avoids the need to use getBean. However, even that is actually unnecessary. If you are writing a standalone application and you DON'T want to include your driver class in application-context.xml, you can use the following code to have Spring autowire the driver's dependencies:
public class AutowireThisDriver {
private MySpringBean mySpringBean;
public static void main(String[] args) {
AutowireThisDriver atd = new AutowireThisDriver(); //get instance
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
"/WEB-INF/applicationContext.xml"); //get Spring context
//the magic: auto-wire the instance with all its dependencies:
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(atd,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
// code that uses mySpringBean ...
mySpringBean.doStuff() // no need to instantiate - thanks to Spring
}
public void setMySpringBean(MySpringBean bean) {
this.mySpringBean = bean;
}
}
I've needed to do this a couple of times when I have some sort of standalone class that needs to use some aspect of my app (eg for testing) but I don't want to include it in application-context because it is not actually part of the app. Note also that this avoids the need to look up the bean using a String name, which I've always thought was ugly.
One of the coolest benefits of using something like Spring is that you don't have to wire your objects together. Zeus's head splits open and your classes appear, fully formed with all of their dependencies created and wired-in, as needed. It's magical and fantastic.
The more you say ClassINeed classINeed = (ClassINeed)ApplicationContext.getBean("classINeed");, the less magic you're getting. Less code is almost always better. If your class really needed a ClassINeed bean, why didn't you just wire it in?
That said, something obviously needs to create the first object. There's nothing wrong with your main method acquiring a bean or two via getBean(), but you should avoid it because whenever you're using it, you're not really using all of the magic of Spring.
The motivation is to write code that doesn't depend explicitly on Spring. That way, if you choose to switch containers, you don't have to rewrite any code.
Think of the container as something is invisible to your code, magically providing for its needs, without being asked.
Dependency injection is a counterpoint to the "service locator" pattern. If you are going to lookup dependencies by name, you might as well get rid of the DI container and use something like JNDI.
Using #Autowired or ApplicationContext.getBean() is really the same thing. In both ways you get the bean that is configured in your context and in both ways your code depends on spring.
The only thing you should avoid is instantiating your ApplicationContext. Do this only once! In other words, a line like
ApplicationContext context = new ClassPathXmlApplicationContext("AppContext.xml");
should only be used once in your application.
One of Spring premises is avoid coupling. Define and use Interfaces, DI, AOP and avoid using ApplicationContext.getBean() :-)
One of the reasons is testability. Say you have this class:
interface HttpLoader {
String load(String url);
}
interface StringOutput {
void print(String txt);
}
#Component
class MyBean {
#Autowired
MyBean(HttpLoader loader, StringOutput out) {
out.print(loader.load("http://stackoverflow.com"));
}
}
How can you test this bean? E.g. like this:
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
// execution
new MyBean(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get, result::append);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
Easy, right?
While you still depend on Spring (due to the annotations) you can remove you dependency on spring without changing any code (only the annotation definitions) and the test developer does not need to know anything about how spring works (maybe he should anyway, but it allows to review and test the code separately from what spring does).
It is still possible to do the same when using the ApplicationContext. However then you need to mock ApplicationContext which is a huge interface. You either need a dummy implementation or you can use a mocking framework such as Mockito:
#Component
class MyBean {
#Autowired
MyBean(ApplicationContext context) {
HttpLoader loader = context.getBean(HttpLoader.class);
StringOutput out = context.getBean(StringOutput.class);
out.print(loader.load("http://stackoverflow.com"));
}
}
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
ApplicationContext context = Mockito.mock(ApplicationContext.class);
Mockito.when(context.getBean(HttpLoader.class))
.thenReturn(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get);
Mockito.when(context.getBean(StringOutput.class)).thenReturn(result::append);
// execution
new MyBean(context);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
This is quite a possibility, but I think most people would agree that the first option is more elegant and makes the test simpler.
The only option that is really a problem is this one:
#Component
class MyBean {
#Autowired
MyBean(StringOutput out) {
out.print(new HttpLoader().load("http://stackoverflow.com"));
}
}
Testing this requires huge efforts or your bean is going to attempt to connect to stackoverflow on each test. And as soon as you have a network failure (or the admins at stackoverflow block you due to excessive access rate) you will have randomly failing tests.
So as a conclusion I would not say that using the ApplicationContext directly is automatically wrong and should be avoided at all costs. However if there are better options (and there are in most cases), then use the better options.
The idea is that you rely on dependency injection (inversion of control, or IoC). That is, your components are configured with the components they need. These dependencies are injected (via the constructor or setters) - you don't get then yourself.
ApplicationContext.getBean() requires you to name a bean explicitly within your component. Instead, by using IoC, your configuration can determine what component will be used.
This allows you to rewire your application with different component implementations easily, or configure objects for testing in a straightforward fashion by providing mocked variants (e.g. a mocked DAO so you don't hit a database during testing)
Others have pointed to the general problem (and are valid answers), but I'll just offer one additional comment: it's not that you should NEVER do it, but rather that do it as little as possible.
Usually this means that it is done exactly once: during bootstrapping. And then it's just to access the "root" bean, through which other dependencies can be resolved. This can be reusable code, like base servlet (if developing web apps).
There is another time when using getBean makes sense. If you're reconfiguring a system that already exists, where the dependencies are not explicitly called out in spring context files. You can start the process by putting in calls to getBean, so that you don't have to wire it all up at once. This way you can slowly build up your spring configuration putting each piece in place over time and getting the bits lined up properly. The calls to getBean will eventually be replaced, but as you understand the structure of the code, or lack there of, you can start the process of wiring more and more beans and using fewer and fewer calls to getBean.
I've only found two situations where getBean() was required:
Others have mentioned using getBean() in main() to fetch the "main" bean for a standalone program.
Another use I have made of getBean() are in situations where an interactive user configuration determines the bean makeup for a particular situation. So that, for instance, part of the boot system loops through a database table using getBean() with a scope='prototype' bean definition and then setting additional properties. Presumably, there is a UI that adjusts the database table that would be friendlier than attempting to (re)write the application context XML.
however, there are still cases where you need the service locator pattern.
for example, i have a controller bean, this controller might have some default service beans, which can be dependency injected by configuration.
while there could also be many additional or new services this controller can invoke now or later, which then need the service locator to retrieve the service beans.
You should to use: ConfigurableApplicationContext instead of for ApplicationContext

Design of generic test class that calls specific method before and after class - for integration test

I want to write a generic test class for special kind of integration test. The generic class has to setup a server before all test in a subclass and tear down after all tests. Each subclass has to provide one string parameter to setup the server.
My problem is to find a good design for it. Since #Before/AfterClass are static the given parameter must be static to. Setting the parameter in constructor of subclass is too late.
I also thought about creating a custom test runner and a custom annotation to set the parameter - but that's probably too much for now?!
Edit:
Because of kind of setup it is essential that setup and tear down is only called once per test class - not for every test.
My Stack is Camel + Guice (Standalone app)
Sounds like you want to use a Rule, in particular perhaps the ExternalResources ones.
By using a ClassRule and runner you should be able to instantiate normal objects and avoid the static methods, but have sub-classes instantiate their own / customised rules to set up your server as required.

How can I unit test this method in java?

I'm working with the Struts2 framework and would like to unit test the execute method below:
public String execute() {
setDao((MyDAO) ApplicationInitializer.getApplicationContext().getBean("MyDAO"));
setUserPrincipal(); //fetches attribute from request and stores it in a var
setGroupValue(); //
setResults(getMyDao().getReportResults(getActionValue(), getTabName());
setFirstResultSet((List) getResults()[0]);
setSecondResultSet((List) getResults()[1]);
return SUCCESS;
}
As you can see most of the logic is database related. So how would I go about unit testing this functionality? I would like to unit test by mocking a HTTPServletRequest with few request variables inside it.
My questions are:
How can I fake/mock a request variable as if its coming from a browser
Should my unit test be calling the actual DAO and making sure that the data is coming back?
If so, how can I call the DAO from unit test since the DAO is tied to the server since jndi pool settings reside on the application server.
I'd appreciate any book/article that shows how to really accomplish this.
The code you have shown us is not enough to fully answer your question.
Line by line
setDao((MyDAO) ApplicationInitializer.getApplicationContext().getBean("MyDAO"));
This is the hardest line since it uses static method. We would need to see how ApplicationInitializer works. In ideal world the getApplicationContext() method should return mock of ApplicationContext. This mock in turns should return MyDAO when getBean("MyDAO"). mockito is perfectly capable of handling this, as well as all other mocking frameworks.
setUserPrincipal(); //fetches attribute from request and stores it in a var
Where does the request come from? Is it injected to action class? If so, simply inject mocked request object, e.g. MockHttpServletRequest.
setGroupValue(); //
Same as above? Please provide more details, what this method actually does?
setResults(getMyDao().getReportResults(getActionValue(), getTabName());
Your previously created mock should return something when getReportResults() is called with given arguments.
setFirstResultSet((List) getResults()[0]);
setSecondResultSet((List) getResults()[1]);
I guess methods below set some field on the action class. Because you have full control over what was returned from mocked getReportResults(), this is not a problem.
return SUCCESS;
You can assert whether SUCCESS was the result of execution.
Now in general
How can I fake/mock a request variable as if its coming from a browser
See above, there is a mock built-in in Spring.
Should my unit test be calling the actual DAO and making sure that the data is coming back?
If your unit test calls real DAO, it is no longer unit test. It is an integration test.
If so, how can I call the DAO from unit test since the DAO is tied to the server since jndi pool settings reside on the application server.
This means you are doing integration testing. In that case you should use in-memory database like h2 so you can still run the test on ci server. You must somehow configure your application to fetch DataSource from different place.
Final note
In essence you should inject mocks of everything to your Struts action class. You can tell mocks to return any value upon calling. Then, after calling execute(), you can verify given methods were called, fields set and result value is correct. Consider splitting this to several tests.
Code review
Struts 2 integrates perfectly with Spring. If you take advantage of that functionality Spring container will automatically inject MyDAO to your action class. The first line becomes obsolete.
This code is hard to unit test because instead of using Spring as intended (i.e. as a dependency injection framework), you use it as a factory. Dependency injection is precisely used to avoid this kind of bean lookup you're doing, which is hard to test. The DAO should be injected into your object. That way, you could inject a mock DAO when unit testing your object.
Also, this logic is not database-related at all. The DAO contains the database-related logic. This action uses the DAO, and the DAO is thus another unit (which should be tested in its own unit test). You should thus inject a mock DAO to unit test this method.
Finally, this method doesn't use HttpServletRequest (at least not directly), so I don't understand why you would need to use a fake request. You could mock the setXxx methods which use the request.
Instead of simply mocking the HTTPServletRequest, how about
mocking an actual automated targeted request to the application
itself? Check out Selenium which lets you do just that.
For testing DAOs (integration testing), you could create your databases in memory using HSQLDB, which will allow you to create / delete objects from your tests, and making sure they are persisted / retrieved properly. The advantage with HSQLDB is that your tests will run much quicker than they will with an actual database. When the time comes to commit your code, you could run the tests against your actual database. Usually, you would setup different run configurations in your IDE to facilitate this.
The easiest way to make your injected daos available to your tests is to let your unit test classes extend AbstractJUnit4SpringContextTests. You could then use the #ContextConfiguration annotation to point to multiple xml application context files, or if you use annotation based configuration, point it to your context file which has the <context:annotation-config /> declaration in it.

Mocking at compile time

I'm working with some legacy code and I need to test that some expensive service is called (it makes network calls, send emails, etc.).
I'm able to inject a fake service instead of the original one by means of the framework in use (jboss seam 2). See this question: Mock #org.jboss.seam.annotations.in behaviour for unittest
I now want my fake object to be a smarter mock to assert if it has been called or not, etc. I would like it to be a Mockito or Easymock or some other thing mock. But constructing the mock the classical way in the test and then injecting it, is not working because of the way seam 2 and seam test deals with injection. See the link above.
Question: is there a way to have my mock extend or be annotated in order to become a Mockito or something mock? How can I get a reference to it in my tests?
I disagree with the answer of the question you linked to. A unit test should test the class independantly from the environment it's supposed to work in. And dependency injection frameworks are precisely used to be able to inject mock dependencies in unit tests, without needing any complex environment to run the unit test.
I don't know Seam, but its documentation says that #In can be placed on a property accessor. I would just have the class under test like this:
public class someBean implements Serializable {
private ApplicationBean applicationBean
#In
protected void setApplicationBean(ApplicationBean applicationBean) {
this.applicationBean = applicationBean;
}
...
}
And I would just call the setter to inject the mock in the unit test.
You could also let the code as is, but provide a setter or an additional constructor to be able to inject a mock applicationBean.
You need a class with the same name but a higher precedence. I've built plenty of mocks just doing that.
You give the same #name to your mock class and you define #install(precedence=MOCK). As soon as this class is in the classpath it will be used instead of your normal class (precedence default is application if I remember correctly).
I have no code ready here just now but I mock the facesmessage for example so during testing I can read these messages from this class and validate them.

Is there ever a case for 'new' when using dependency injection?

Does dependency injection mean that you don't ever need the 'new' keyword? Or is it reasonable to directly create simple leaf classes such as collections?
In the example below I inject the comparator, query and dao, but the SortedSet is directly instantiated:
public Iterable<Employee> getRecentHires()
{
SortedSet<Employee> entries = new TreeSet<Employee>(comparator);
entries.addAll(employeeDao.findAll(query));
return entries;
}
Just because Dependency Injection is a useful pattern doesn't mean that we use it for everything. Even when using DI, there will often be a need for new. Don't delete new just yet.
One way I typically decide whether or not to use dependency injection is whether or not I need to mock or stub out the collaborating class when writing a unit test for the class under test. For instance, in your example you (correctly) are injecting the DAO because if you write a unit test for your class, you probably don't want any data to actually be written to the database. Or perhaps a collaborating class writes files to the filesystem or is dependent on an external resource. Or the behavior is unpredictable or difficult to account for in a unit test. In those cases it's best to inject those dependencies.
For collaborating classes like TreeSet, I normally would not inject those because there is usually no need to mock out simple classes like these.
One final note: when a field cannot be injected for whatever reason, but I still would like to mock it out in a test, I have found the Junit-addons PrivateAccessor class helpful to be able to switch the class's private field to a mock object created by EasyMock (or jMock or whatever other mocking framework you prefer).
There is nothing wrong with using new like how it's shown in your code snippet.
Consider the case of wanting to append String snippets. Why would you want to ask the injector for a StringBuilder ?
In another situation that I've faced, I needed to have a thread running in accordance to the lifecycle of my container. In that case, I had to do a new Thread() because my Injector was created after the callback method for container startup was called. And once the injector was ready, I hand injected some managed classes into my Thread subclass.
Yes, of course.
Dependency injection is meant for situations where there could be several possible instantiation targets of which the client may not be aware (or capable of making a choice) of compile time.
However, there are enough situations where you do know exactly what you want to instantiate, so there is no need for DI.
This is just like invoking functions in object-oriented langauges: just because you can use dynamic binding, doesn't mean that you can't use good old static dispatching (e.g., when you split your method into several private operations).
My thinking is that DI is awesome and great to wire layers and also pieces of your code that needs sto be flexible to potential change. Sure we can say everything can potentially need changing, but we all know in practice some stuff just wont be touched.
So when DI is overkill I use 'new' and just let it roll.
Ex: for me wiring a Model to the View to the Controller layer.. it's always done via DI. Any Algorithms my apps uses, DI and also any pluggable reflective code, DI. Database layer.. DI but pretty much any other object being used in my system is handled with a common 'new'.
hope this helps.
It is true that in today, framework-driven environment you instantiate objects less and less. For example, Servlets are instantiated by servlet container, beans in Spring instantiated with Spring etc.
Still, when using persistence layer, you will instantiate your persisted objects before they have been persisted. When using Hibernate, for example you will call new on your persisted object before calling save on your HibernateTemplate.

Categories

Resources