How to force the static block running in each test method? - java

I found static block is running only once when I execute multiple JUnit tests. How can I force it to run for each test method? I am using latest JUnit 4.8.2
Also, according to xUnit design principle, every method should be totally independent on others. Why static block only be executed once?
#Test TestMethod1 () {
Accounts ac = new Accounts();
ac.method1(); //kill the thread inside
}
#Test TestMethod2 () {
Accounts ac = new Accounts();
ac.method2(); // the thread is no longer available!!
}
class Accounts {
static {
// initalize one thread to monitor something
}
}
This even happens when TestMethod1 and TestMethod2 are in the different Test Classes.

static blocks are only executed on class loading because that is what they are: class initializers. To have a static block run multiple times would require you to unload the class (not an easy thing to do...).
If you need to use static blocks, you can come up with ways to test them. Why not unwrap the block into a public (static) method? All you have to do in that world is test the method:
static {
staticInitMethod();
}
public static void staticInitMethod(){
//insert initialization code here
}
you also might be able to get away with just an ordinary initializer
{//not static
//insert initialization code here
}
Although, the truth is most code doesn't need to use initializers like this at all.
Edit: Turns out Oracle likes the static method approach http://download.oracle.com/javase/tutorial/java/javaOO/initial.html

Why static block only be executed once?
Because that is the whole point of static initializer blocks!
Or to put it another way, if you want some initialization code to execute multiple times, put it in a regular constructor or method, or (in a tiny number of cases) a non-static initializer block.
In the context of JUnit, the normal way to implement test startup and shutdown code using setUp() and tearDown() methods.
If you are trying to unit test the execution of static initialization in your own code, you are in for a rough road I think. But then, unit testing of code with static state (e.g. singletons) is always difficult ... and that's one of the reasons that people think that static state is a bad idea.
Consider using a Dependency Injection (aka Inversion of Control) framework instead of singletons.
Alternatively, consider modifying your singletons / static initialization code to make it easier to test. For instance, add a static method that allows a test to re-execute the initialization. (And before you say that this breaks the singleton pattern: yes I know. You need to choose between design / implementation "purity" and ease of testing.)

Is the static code for the tests for the class being tested?
If the code is static so the tests can share, then you need to move the code into its own class. Then either have the test class constructor instantiate a static instance or create a test suite that does the same thing.
If you want each test to stand alone, then move what you are doing in your static block into the setup()/teardown() methods, it's what they are there for.

Static block is executed only once when first time class is loaded into JVM. Junit provide #Before annotation which is basically used for required initialization fro test case. This can be used for executing static blocks of class. for example I have following class Car
public class Car implements Vehicle{
private String type = "lmv";
static {
VehicleFactoryWithoutRefl.getInstance().registerVehicle("car", new Car());
}
#Override
public void moveForward() {
}
#Override
public String getType() {
return type;
}
#Override
public Vehicle createVehicle() {
return new Car();
}
}
and I want to execute static block of this class in Junit before creating the car instance. I have to load this class in setUp() using class.forName("package.ClassName") Junit code.
public class TestFactory {
#Before
public void setUp() {
try {
Class.forName("com.cg.dp.factory.Car");
} catch (ClassNotFoundException e) {
//e.printStackTrace();
}
}
#Test
//#Ignore
public void testFactoryInstanceWithoutRefl() {
Vehicle v1 = VehicleFactoryWithoutRefl.getInstance().newVehicle("car");
assertTrue(v1 instanceof Car);
}
}

Um... make it non-static? You can have instance initializer blocks too (same as static blocks, just without the static keyword). But test setup code should actually go into an explicit setUp() or #Before method.

Related

Refactoring static mocks in Mockito 3.4

I have a Jupiter based UnitTest in a java project where I need to mock some static methods of an external utility. Mockito 3.4 allows for mocking static methods, so no need for PowerMock any more. We all use static mocks by defining them in a try(){} block and overwriting methods on those static mocks inside the block. All fine, but things sometimes get annoying when you have to implement a non trivial mocking cascade. Which is especially annoying of you have to do that in several test cases inside your test class.
class ClassA {
public static void methodA() { ... }
public static void methodB() { ... }
}
class ClassB {
public static void methodA() { ... }
public static void methodB() { ... }
}
class ClassC {
public static void methodA() { ... }
public static void methodB() { ... }
}
class ClassX {
public int doSomething() {
// does something using static methods from classes ClassA, ClassB, ClassC
return 3;
}
}
A test class might (roughly) look like that (please excuse typos and nonsense, this is only meant as a demonstration, this is not working code):
#Test
void test_doSomething() {
int result = 0;
ClassX classX = new ClassX();
try (MockedStatic<ClassA> classAMockStatic = Mockito.mockStatic(ClassA.class);
MockedStatic<ClassB> classBMockStatic = Mockito.mockStatic(ClassB.class);
MockedStatic<ClassC> classCMockStatic = Mockito.mockStatic(ClassC.class)) {
// this is a block where static methods get overwritten, also some mocks are created
// this code does not make sense, it is just to demonstrate the issue of non trivial mocking scenarios
// situations like this often arise when mocking building patterns for example
classAMockStatic.when(ClassA::methodA).thenReturn("fooA");
ClassB classBMock = mock(ClassB.class);
when(classBMock.methodA()).thenReturn("barA");
classAMockStatic.when(ClassA::methodB).thenReturn(classBMock);
ClassC classCMock = mock(ClassC.class);
when(classCMock.someMethodA()).thenReturn("abc");
when(classCMock.methodA()).thenReturn("barA");
classAMockStatic.when(ClassA::methodA).thenReturn(classCMock);
// and so on and so on, you get the idea
result = classX.doSomething();
}
assertThat(result).equals(3);
}
Typically the question arises if this cannot be refactored to implement the mocking cascade only once. And use it in several test cases. I tried that, I was surprised to find that some of my overwritten methods worked as expected, but not all. I failed to find a working solution:
// THIS DOES NOT WORK
#Test
void test_doSomething() {
int result = 0;
ClassX classX = new ClassX();
try (MockedStatic<ClassA> classAMockStatic = createStaticMockA();
MockedStatic<ClassB> classBMockStatic = createStaticMockB();
MockedStatic<ClassC> classCMockStatic = createStaticMockC()) {
result = classX.doSomething();
}
assertThat(result).equals(3);
}
private MockedStatic<ClassA> createStaticMockA() {
MockedStatic<ClassA> classAMockStatic = Mockito.mockStatic(ClassA.class);
classAMockStatic.when(ClassA::methodA).thenReturn("fooA");
ClassB classBMock = mock(ClassB.class);
when(classBMock.methodA()).thenReturn("barA");
classAMockStatic.when(ClassA::methodB).thenReturn(classBMock);
return classAMockStatic;
}
private MockedStatic<ClassB> createStaticMockB() {
MockedStatic<ClassB> classAMockStatic = Mockito.mockStatic(ClassB.class);
ClassB classBMock = mock(ClassB.class);
when(classBMock.someMethodA()).thenReturn("aaa");
when(classBMock.someMethodB()).thenReturn("bbb");
when(classBMock.methodA()).thenReturn("barA");
classBMockStatic.when(ClassB::methodA).thenReturn(classBMock);
return classBMockStatic;
}
private MockedStatic<ClassC> createStaticMockC() {
MockedStatic<ClassC> classAMockStatic = Mockito.mockStatic(ClassC.class);
ClassC classCMock = mock(ClassC.class);
when(classCMock.someMethodA()).thenReturn("abc");
when(classCMock.methodB()).thenReturn("barC");
classCMockStatic.when(ClassC::methodA).thenReturn(classCMock);
return classCMockStatic;
}
So this looks cleared up, but does not work.
I know that I obviously could just extract the mocking section into a method and call that first in the try block. But that separates the static setup from the mock generation. And it is not as clean as my idea.
Yes, I tried implementing an execution method which accepts a lambda holding the code actually meant to be executed. So that the try(){} block gets stowed away into a method, leaving only the call to that method with a lambda in the test case. Works, but is hard to read and to understand. Not a good solution in my experience.
And yes, I also know that one should try to refactor production code so that it is easier to mock it. Sometimes that is simply not possible (read: external dependencies).
So what are my questions here?
does anyone have an idea how to achieve a clean, refactored look which actually works?
can anyone explain to me why some of the overwritten methods work as expected while others don't? I know, all the examples on the internet demonstrate that you use the straight approach, but the examples are obviously showing trivial situations.
is it really true that no one else is annoyed by that situation of have to setup the mock cascade exactly where it confuses? And that you have to reimplement it for each test case?
As Tim Moore suggests, if you have:
class StaticUtil {
public static void foo() { ... }
}
You can introduce an interface and an implementation to inject into your clients:
interface Util {
void foo();
}
class DefaultUtil {
public void foo() {
StaticUtil.foo();
}
This makes writing tests simpler as you can just mock Util in the normal way.

Execution order of methods when #Test is at class level

There are a lot of questions on the execution order of TestNG tests, but I haven't found one that specifically answers this question - unless I just cannot find it.
I know there's things to do that can achieve what I'm looking for, such as:
#Test above every test method within the class with the use of Priority
#Test above every test method within the class with the use of Depends on
The use of preserve-order in the XML file
However, what I want to know is:
If you declare #Test at the class level, not the method level, how to "preserve" the order in which the methods are declared? Can you even do this?
For example, if my class looks like this:
#Test
public class mySampleClass
{
public void test()
{
//Run first - First method in the class
}
public void run()
{
//Run second - Second method in the class
}
public void execute()
{
//Run last - Last method in the class
}
}
Can I ensure that when I run this that the methods are executed in the order they are within the class instead of alphabetically?
Not sure why you want your tests to run that way, Even though it is not possible to do it directly, it IS possible using a MethodInterceptor:
public class MyInterceptor implements IMethodInterceptor {
// keep your list of method names in order
private static final List<String> order = List.of("test", "run", "execute");
#Override
public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
methods.sort(Comparator.comparing(m -> order.indexOf(m.getMethod().getMethodName())));
return methods;
}
}
Now add the #Listeners(value = MyInterceptor.class) annotation to your class.
NOTE: List.of is available only in java 9+, if you are using a lower version, you could use Arrays.asList.

How should I mock out a single method inside an object I'm trying to test?

I have a problem with a class that I am testing where in almost every method I want to test, one of the first things each method does is call this one specific method. This method that is called once by all of these other methods takes a long time to execute. I don't want to have to wait for this every time I run my tests, it really is just a huge waste of time.
I attempted to #Spy the method using Mocktio, but I ran into problems because the really long method doesn't return anything. Can someone suggest a good way to mock out a single method inside a class I am trying to test?
Example:
public class myClass {
public void methodOne() {
reallyLongMethod();
// More code
}
public void methodTwo() {
reallyLongMethod();
// More code
}
.
.
.
public void methodN() {
reallyLongMethod();
// More code
}
public void reallyLongMethod() {
}
}
This is the class I am trying to test. I want to test all of the 'methodX()' methods. I don't want to run reallyLongMethod everysingle time however.
So, is there a way to use Mockito 'Spy' to stub out reallyLongMethod()? Even though it doesn'treturn anything?
You can use a Spy with doNothing(), but make sure you use the spy during the test. Mockito spies copy the original, instead of delegating to it.
#RunWith(MockitoJUnitRunner.class)
public class YourTest {
// Option 1:
// #Spy MyClass myClass = new MyClass();
// Option 2 (see #Before method)
MyClass myClass;
#Before public void ignoreReallyLongMethod() {
myClass = spy(new MyClass()); // discard original
doNothing().when(myClass).reallyLongMethod();
}
#Test public void methodOneWorks() {
myClass.methodOne(); // you're using the spy here
assertEquals(42, myClass.getFoo());
}
}
Though this does evoke a code smell, don't mock or stub the class under test, as long as you're careful to test the method behavior (methodOne) and not the stubbed behavior (reallyLongMethod) you'll be good to go. If you do want to test reallyLongMethod you'll want to use a different object instance or else you'll "test" the doNothing() call alone. Do bear in mind that if reallyLongMethod and your other methods have any negative interactions, these tests won't tell you about that.
By the way, you can also do the equivalent without using Mockito, which may make a little clearer what you are or aren't doing with your mocks:
#RunWith(JUnit4.class)
public class YourTest {
MyClass myClass;
#Before public void createMyClass() {
myClass = new MyClass() { // create an anonymous inner class
#Override public void reallyLongMethod() {} // that does nothing here
};
}
}

JUnit: initialization of static final attributes

Oftentimes in my unit tests I have fixtures that are read from resource files and stored into a static attribute on the test class:
public class TestFoo {
private static String fileContents;
#BeforeClass
public static void setup() throws IOException {
fileContents = ... read TestFoo.class.getResourceAsStream("filename") ...
}
}
Which works, but the problem I have is that I generally don't like non-final static data in my tests as it allows for the possibility of one test case to affect the output of another (in the above example if one test reassigned fileContents to something else, then there would be side-effects in other tests that make use of the fixture data).
If I add the final modifier though, then the assignment has to happen at declaration, which is a problem when the initialization is non-trivial (such as in the above example where a checked exception could be triggered by the initialization code). An alternative is to use a static initializer block:
public class TestFoo {
private final static String fileContents;
static {
try {
fileContents = ... read TestFoo.class.getResourceAsStream("filename") ...
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
But I don't particularly like this approach due to the verbosity of having to write a try/catch.
Which approach is more common/idiomatic Java, or is there a better/more typical way to have a static final resource initialized?
I'd use #BeforeClass because it's less verbose. If you fear that someone might accidentally overwrite the value, you could also use #Before. Unless the file is very large, the runtime overhead is probably negligible.

How can I get #BeforeClass and #AfterClass equivalent in Junit3?

I want to back up my application's database before replacing it with the test fixture. I'm forced to use Junit3 because of Android limitations, and I want to implement the equivalent behavior of #BeforeClass an #AfterClass.
UPDATE: There is now a tool (Junit4Android) to get support for
Junit4 on Android. It's a bit of a kludge but should work.
To achieve the #BeforeClass equivalent, I had been using a static variable and initializing it during the first run like this, but I need to be able to restore the database after running all the tests. I can't think of a way of detecting when the last test has run (since I believe there is no guarantee on the order of test execution.)
public class MyTest extends ActivityInstrumentationTestCase2<MainActivity> {
private static boolean firstRun = true;
#Override
protected void setUp() {
if(firstRun) {
firstRun = false;
setUpDatabaseFixture();
}
}
...
}
From the junit website:
Wrapped the setUp and tearDown method in the suite.This is for the
case if you want to run a single YourTestClass testcase.
public static Test suite() {
return new TestSetup(new TestSuite(YourTestClass.class)) {
protected void setUp() throws Exception {
System.out.println(" Global setUp ");
}
protected void tearDown() throws Exception {
System.out.println(" Global tearDown ");
}
};
}
If you would like to run only one setUp and tearDown for all the
testcase, make a suite and add testClass to it and pass the suite
object in TestSetup constructor.But I think there is not much usage
for this,and in a way it is violating JUnit philosophy.
Recently, I was looking for a similar solution too. Fortunately, in my case after the JVM exits after the last test is run. So I was able to achieve this by adding a JVM shutdown hook.
// Restore database after running all tests
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
restoreDatabase();
}
});
hope this helps.
I would suggest avoiding these kind of dependencies where you need to know the order in which tests are run. If all you need is to restore a real database that was replaced by setUpDatabaseFixture() probably you solution comes from the use of a RenamingDelegatingContext. Anyway, if you can't avoid knowing when the last test was run, you can use something like this:
...
private static final int NUMBER_OF_TESTS = 5; // count your tests here
private static int sTestsRun = 0;
...
protected void tearDown() throws Exception {
super.tearDown();
sTestsRun += countTestCases();
if ( sTestsRun >= NUMBER_OF_TESTS ) {
android.util.Log.d("tearDow", "*** Last test run ***");
}
}
Isn't this (dealing elegantly with data, so you don't have to worry about restoring it) what testing with mock objects are for? Android supports mocking.
I ask as a question, since I've never mocked Android.
In my experiences, and from this blog post, when the Android tests are made into a suite and run by the InstrumentationTestRunner - ActivityInstrumentationTestCase2 is an extension of ActivityTestCase which is an extendsion of InstrumentationTestCase - they are ordered alphabetically using android.test.suitebuilder.TestGrouping.SORT_BY_FULLY_QUALIFIED_NAME, so you can just restore you DB with a method that is the lowes in the alphabet out of your test names, like:
// underscore is low in the alphabet
public void test___________Restore() {
...
}
Note:
You have to pay attention to inherited tests, since they will not run in this order. The solution is to override all inherited test and simply call super() from the override. This will once again have everything execute alphabetically.
Example:
// Reusable class w only one time setup and finish.
// Abstract so it is not run by itself.
public abstract class Parent extends InstrumentationTestCase {
#LargeTest
public void test_001_Setup() { ... }
#LargeTest
public void test_____Finish() { ... }
}
/*-----------------------------------------------------------------------------*/
// These will run in order shown due to naming.
// Inherited tests would not run in order shown w/o the use of overrides & supers
public class Child extends Parent {
#LargeTest
public void test_001_Setup() { super.test_001_Setup(); }
#SmallTest
public void test_002_MainViewIsVisible() { ... }
...
#LargeTest
public void test_____Finish() { super.test_____Finish(); }
}

Categories

Resources