Spring inject resource used by static method - java

I have a Unit test set up as follows:
Unit Test using Mockito runs and creates an Object (class is not using Spring)
Object calls a static method in a utility class (Spring Component) called TimeUtil during its construction
TimeUtil has a field called TimeService (static Spring Component) that fetches the time
Workflow: Unit Test -> Create Object -> Static method call in TimeUtil -> Fetch time from TimeService
This workflow works fine in production however it has been challenging to test, for some reason the TimeService in TimeUtil is always null. Spring is supposed to inject an instance of TimeService into TimeUtil at runtime.
Can anyone advise on why my TimeService keeps coming back as null?
I tried using Mockito to capture the static method call but this didn't work, similarly I can't inject a TimeService mock into the object class since this statically calls TimeUtil.

You need to look through the Spring configuration to find out how you (or someone from your team) made Spring wire up the static TimeService. Normally, Spring only works on beans which it created. So global variables and static methods are not supported. Someone must have written code to make the injection happen in this case.
Show us this code and we can help you improve it to allow for unit tests.

Related

Can JMockit initiate mock objects with argument constructor?

When I put the #Mocked annotation on a object which has only constructor with parameters, will this object be initiated rightly?
When I put the #Mocked annotation on a object which has only constructor with parameters, will this object be initiated rightly?
No.
A mock will be created that has the same interface. That means it will have the same public methods and if the test class is in the same package it will also have the same protected and package private methods accessible.
This mock will not invoke the real methods of the mocked class (unless you configure it so).
This means that for every method that is expected to be called by your code under test (cut) and that has a return value defined you have to configure your mock so that is returns a value your cut shall work with in that particular test.
This configurable return values and the verify capabilities of the mocks are the reason why we use mocking frameworks.
Attention
If you want to mock the call to a method which accesses a member initialized by the mocked classes constructor you have to use the form
doReturn(SOME_VALUE).when(mock).methodToBeCalledByYourCut();
because the form
when(mock.methodToBeCalledByYourCut()).thenReturn(SOME_VALUE);
will raise a NullPointerException in that special case.

Anyway to create a Test Helper class that creates mocks?

In my testing of a legacy system, I have found myself having to mock similar classes for different parts of the system I'm increasing test coverage for. I would like to create a helper class for my tests that could call a method that would set up particular mocks and their return values.
Here's an example of a method I have had to create a few times in multiple tests.
public void mockClassINeedToMockToReturn(Boolean bool){
mockStatic(classINeedToMock.class);
when(classINeedToMock.getSuccess(Mockito.any(someClass.class))).thenReturn(bool);
}
I have tried setting this up in a HelperTest.class (in the same project/folder as my tests) and it isn't working. I have included both the following Annotations in the class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({classINeedToMock.class})
I have tried:
Using the methods statically and calling them in my tests. (does not mock)
Creating a HelperTest object and calling the method in my test. (still does not mock)
Having my tests Extend my HelperTest.class and calling the method from in my tests. (Still refuses to mock the class)
I'm sure this is something to do with the way the PowerMockRunner works. So is there a way to make this work? Or should I just come to terms with duplicating these methods throughout my project.
It's the little details.... When looking into it more I noticed the class I was mocking had 2 separate methods.
theClass.method(var1, var2);
theClass.method(var1, List<var2>);
One of my tests was calling the first method, the other was calling the second method. When I ran the second test (only having mocked the first method), it was calling the actual class because that method was not mocked.
After setting up the correct mock with the proper input parameters I could call the method statically and the mock would be created and used appropriately.

Can I make code run before the constructor using annotations

I am using Guice to create and inject instances in my application.
For testing purposes I created a class that is responsible for creating all the static instances needed for a specific test class and inject them. Let's call this class GuiceGraphBuilder.
I want to create and initiate the GuiceGraphBuilder before my mock / test class constructor is called, as some of my mock classes requires the injection to happen on construction time.
Currently I am using a static constructor that initiate GuiceGraphBuilder and populate bunch of static fields.
Is there a way to use some kind of annotation to make a code run before the constructor does?
I have seen an answer that uses Guice, but this of course is not good in my case, since I want to create the Guice injector in the generated code.
I suppose you test using junit? Then you have the lifecycle hooks
#BeforeClass - run once before first test (use for static setup)
#Before - run before every test method
#After - run after each test method
#AfterClass - run once after all tests finished
I suppose that, arbitrary from guice, you will be able to solve your problem by matching init and clean up to the correct phase.

How to avoid SpringJUnit4ClassRunner initializing beans before them being mocked with JMockit?

I have a JUnit test class like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration( locations = { "beanDefinitions.xml"})
public class MyTest {
#Mocked private SomeDependency usedInSpringContext;
#Test public void letsTest() {
...
}
}
The problem is, Spring runner loads its beans before JMockit gets a chance to mock them. How to avoid it? This is JMockit 1.0 and Spring 3.07. I'd rather had my beanDefinitions.xml unchanged.
The code under test is legacy. It contains lots of hardcoded spring dependencies I cannot get rid of easily. Thus the first step - mocking.
You can use a custom FactoryBean.
It is explained in this blog. And here is the example code.
It uses either easymock or Mockito. But I am sure you can easily port that to JMockit.
EDIT: I overlooked that you don't want your beanDefinitions.xml to be modified. But my suggestion includes that modification.
One of the great things about Spring, and dependency injection in general, is that your classes don't get cluttered up with code to satisfy thier dependencies. They just sit and wait for someone else to fill in collaborating objects. So it is supposed to be trivial to plug in mock objects.
// no Spring runner or context configuration
public class FooTest {
Foo foo;
#Before
public void setup() {
foo = new Foo();
foo.setDependency(mock(dependency)); // details depend on mocking framework
}
}
With this approach you don't autowire or otherwise inject the object you're testing, at least not if you intend to reconfigure it by pointing it at mock collaborators. If the code under test has lots of dependencies, you can wind up with a ton of setup code, but that's normal.
Admittedly, some things (like databases) are hard to mock, so you need a different testing approach to verify that your SQL queries (for example) do what you meant. This starts with a separate bean definitions file containing something like:
<jdbc:embeded-database id="datasource"/>
See http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/testing.html for more information.
The tricky part is that if you haven't been writing Junit tests all along, your may have gotten into a situation where every bean seems to depend on every other bean. So the "unit" you're trying to test isn't one class, but an bunch of interrelated classes. In that case I suggest breaking the bean definitions file into smaller parts, then write unit tests for each part.
With that approach you can let Spring wire up the code under test, because the Spring configuration is part of the unit. The unit test code still mocks and plugs in the dependencies external to that unit.
If you insist on using your real beanDefinitions.xml file in its entirety, you're writing integration tests, not unit tests.

how to mock class which calls singleton class using junit

I would like to test a method from class1 which calls the singleton class getInstance:
Class ivDomain {
public String method1() {
id=Singleton.getInstance().generateId()
... code
}
}
When I do the test using Junit I am getting NullPointerException on the singleton class. How can I fix this?
Classes using statically accessed singletons are a pain to test. Change you ivDomain class to rather take the singleton instance as a parameter to it's constructor and then mock it normally. You should use a Dependency Injection framework (such as Guice) going forward to make this style of development easier.
You shouldn't have to mock Singleton; just change the code so getInstance() doesn't return a null.
The most likely reason - without examining your Singleton's code - is that it's initialization fails to load some external configuration and therefore fails.
Singletons in Automatic Unit Tests can be a problem since sometimes you like them to behave differently for the specific scenario you test (e.g. you want one scenario where generateId returns -1, another when it returns 4354353 and another when it throws a RuntimeException - just so you can see how the code that uses the Singleton works. In such cases a change of design is recommended as Singletons are not amongst the favored design patterns and are somewhat regarded as anti-patterns.
check
mocking a singleton class

Categories