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.
Related
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.
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.
Under JUnit4, I have a test suite which uses a #classrule annotation to bootstrap a framework. This is needed to be able to construct certain objects during tests. It also loads some arbitrary application properties into a static. These are usually specific to the current test suite and are to be used by numerous tests throughout the suite. My test suite would look something like this (where FrameworkResource extends ExternalResource and does a lot of bootstrap work):
#RunWith(Suite.class)
#SuiteClasses({com.example.test.MyTestCase.class})
public class MyTestSuite extends BaseTestSuite {
#ClassRule
public static FrameworkResource resource = new FrameworkResource();
#BeforeClass
public static void setup(){
loadProperties("props/suite.properties")
}
}
The above works really well and the main build has no problem executing all testsuites and their respective test cases (SuiteClasses?). The issue is when I'm in eclipse and I want to run just one test case individually withough having to run the entire suite (as part of the local development process). I would right click the java file Run As > JUnit Test and any test needing the framework resource or test properties would fail.
My question is this:
Does JUnit4 provide a solution for this problem (without duplicating the initialization code in every test case)? Can a Test Case say something like #dependsOn(MyTestSuite.class)?.
If Junit doesn't have a magic solution, is there a common design pattern that can help me here?
As you are running just one test class, a good solution would be to move the initialisation code to the test class. You would need to add the #Before annotation to initialise the properties.
That would require that you duplicate the code on all your tests classes. For resolving this, you could create an abstract parent class that has the #Before method so all the child classes have the same initialization.
Also, the initialised data could be on static variables for checking if it is already initialised for that particular execution.
Why the #BeforeClass method in JUnit is static whereas in TestNG its non-static? TestNG was developed as an improvement over JUnit, so why did they choose this way of implementation?
Since #BeforeClass runs only once, so making it static makes more sense than making it non static. Also in TestNG, on which instance the #BeforeClass method is called? Can someone cite an example for better understanding?
The main difference between JUnit and TestNG is the test class instantiation. JUnit always creates a new instance of the test class for each test method run. TestNG only creates one test class instance and then runs all test methods of this instance.
The JUnit approach guarantees the independency of all test methods. It just does not matter, in which order they run. Additionally, all instance fields are always setup the same for each test method. Initializing data, that is common for all test methods, must take place at the class level, thus it must be static. This is the reason, why the #BeforeClass method must be static.
The TestNG approch does not guarante the independency. In fact, you cannot use an instance field in the same manner as in JUnit tests. If you change such a field in one test method, the changed value is still observabl in another test method. However, this behavior has also an advantage: Sometimes there are dependencies between some test methods. With TestNG, a tester can express them.
Because of the one-instance-approach of TestNG, the #BeforeClass setup can also be a non-static method, but it is still run only once. It was a design decision, but testers using TestNG must be aware of that.
Making a method static or non-static has nothing to do with being able to invoke that method only once at the beginning. You can call a static method as many times as you want. You can call a non-static method exactly one. There is no necessary correlation between the two : being static and invoking once. At least, I am not aware of any direct consequence of making a method static which enables it to be invoked exactly once. static is rightly associated with single class, but not with single invocation.
Making a method static prevents it from accessing non-static members of the class. But with having a non-static #BeforeClass method, you can also access non-static members, there by giving you more scope to access class variables. Perhaps this is the reason why testng removed the restriction of #BeforeClass method being static.
I very much understand what #BeforeClass is. It is executed once before JUnit test run is started & #Before method is executed before every test case.
My question is regarding a very old post by a very senior stackoverflow user (Péter Török
68.8k) Please refer [stackoverflow question]
[1]: JUnit: using constructor instead of #Before which was posted about 2 yrs ago but on JUnit4. so I think it is still valid and true.
Here he mentions
#Before is equivalent to constructor of test class
and
JUnit creates a new instance of the test class for each #Test,
So how does JUnit manage running #BeforeClass only once which is defined inside the test class?
Methods annotated with #BeforeClass must be static. JUnit doesn't need any instance of the test class to call it.
Well, jUnit could run the method annotated with #BeforeClass at time of class loading, that is like you would implement on your own with a static initializer.
You get also the hint that jUnit is doing something like this by the fact that #BeforeClass and #AfterClass annotated methods must be static.
That's because #BeforeClass has to be a static method. Once it is static, JUnit knows how to run it once.
Sometimes several tests need to share computationally expensive setup (like logging into a database). While this can compromise the independence of tests, sometimes it is a necessary optimization. Annotating a public static void no-arg method with #BeforeClass causes it to be run once before any of the test methods in the class. The #BeforeClass methods of superclasses will be run before those the current class. Static methods are not belongs to instances of the class. Those are properties of the class.