Currently I have a strange behavior of my test.
For my test I'm using Groovy and JUnit 4. Groovy has his own strang logic, so don't worry about my code :D
Example 1:
#Log
class Test {
private static def filledFormFields = [
a: 1,
b: 2
]
#Before
void check() {
filledFormFields.each { k, v ->
log.info("$k -> $v")
}
}
#Test
void testA() {
System.exit(0)
}
}
log.info prints all information of filledFormFields (even it is static, yes it has to be static in my case).
Example 2:
#Log
class Test extends Manager {
private static def filledFormFields = [
a: 1,
b: 2
]
#Test
void testA() {
System.exit(0)
}
}
#Log
abstract class Manager {
#Before
void check() {
filledFormFields.each { k, v ->
log.info("$k -> $v")
}
}
}
log.info prints nothing, but why?
Why is my filledFormFields static?
Currently I'm creating Selenium/Geb JUnit Tests with Groovy. Each test instantiates the filledFormFields variable new. In my case I don't want that, because of that it's static. Also it's private because I have multiple test classes that useses this variable just with other equally other information. That was the only solution that I found to keep the varibales only in a class and not instantiated on every test.
Related
How can I mock a class which is used in another class using only powerMock or EasyMock,I can only use this two frameworks ,I know we can use Mockito but as our codebase contains only easymock and powermock library I have to stick the two frameworks only .
I have below code ( I am using powerMock )
public class ClassUnderTest {
public void getRecord() {
System.out.println("1: In getRecord \n");
System.out.println("\n 3:"+SecondClass.getVoidCall());
System.out.println("\n 4: In getRecord over \n");
}
}
I want to mock the method SecondClass.getVoidCall() .
public class ArpitSecondClass {
public static int getVoidCall() {
System.out.println("\n 2: In ArpitSecondClass getVoidCall for kv testing\n");
return 10;
}
}
My Unit Test code is
#RunWith(PowerMockRunner.class)
#PrepareForTest(TestArpit.class)
public class UniteTestClass {
#Test
public void testMock() throws Exception {
SecondClass class2 = createMock(SecondClass.class);
expect(class2.getVoidCall()).andReturn(20).atLeastOnce();
expectLastCall().anyTimes();
ClassUnderTest a=new ClassUnderTest ();
a.getRecord();
replayAll();
PowerMock.verify();
}
}
Basically I want the output as below
1: In getRecord
2: In ArpitSecondClass getVoidCall for kv testing
3:20 (Note:This should be overriden by the value I supplied in UnitTest)
4: In getRecord over
But the output which I am getting with the Unitest code is
2: In ArpitSecondClass getVoidCall for kv testing
The code flow doesnt go beyond expect(class2.getVoidCall()).andReturn(20).atLeastOnce();
And the remaining statments in getRecord are not printed as it's never called at all.
Am I missing something here ?
The SecondClass#getVoidCall() method (public static int getVoidCall() {...}) is a static method and, as such, the mocking is a little different.
Replace the first two lines:
#Test
public void testMock() throws Exception {
SecondClass class2 = createMock(SecondClass.class);
expect(class2.getVoidCall()).andReturn(20).atLeastOnce();
With the lines below (and prepare the class):
import static org.easymock.EasyMock.expect;
import static org.powermock.api.easymock.PowerMock.mockStatic;
...
#RunWith(PowerMockRunner.class)
#PrepareForTest({TestArpit.class, SecondClass.class}) // added SecondClass.class here
public class UniteTestClass {
#Test
public void testMock() throws Exception {
mockStatic(SecondClass.class); // changed this line
expect(SecondClass.getVoidCall()).andReturn(20).atLeastOnce(); // changed this line
I have the following skeleton of code in a JAVA class called "TestClass.Java":
public String functionA () {
if (function B() == true) {
String testVariable = function C();
String test2 = testVariable +"Here a test";
} else {
...
}
}
I need to apply unit tests for this function functionA() where tests had been applied on functionB() and functionC():
I did below:
private TestClass mockTestClass ;
#Test
public void testFunctionA() {
mockTestClass = Mockito.mock(TestClass.class);
private MockComponentWorker mockito;
Mockito.when(mockTestClass.functionB()).thenReturn(true);//already test is done;
Mockito.when(mockTestClass.functionC()).thenReturn("test"); //already test is done;
mockito = mockitoContainer.getMockWorker();
mockito.addMock(TestClass.class,mockTestClass);
mockito.init();
assertEquals("PAssed!", "test Here a test", mockTestClass.functionA());
}
When I ran my test, I got: NULL in mockTestClass.functionA().
Can you please help? How to test this function?
You would generally want to mock other classes and not the class you are actually testing. But for your example if you really want to mock calling functionB() and functionC() you need to spy on TestClass. And instead of Mockito.when(mockTestClass.functionB()).thenReturn(true) you need doReturn(true).when(mockTestClass).functionB() (same goes for functionC()). Only then your assertEquals("PAssed!", "test Here a test", mockTestClass.functionA()) will call the actual method functionA() and pass.
Groovy test does not create a mock for static class, when that class is used inside other Java class. Below is a code snippet that proves this
Java class under test:
public class JavaClass {
public void method() {
ClassWithStaticMethod.doSomething();
}
}
Java class with static method:
public class ClassWithStaticMethod {
public static void doSomething() {
System.out.println("Static method called");
}
}
Groovy test that fails:
class JavaClassTest extends Specification {
def 'test'() {
given:
GroovyMock(ClassWithStaticMethod, global: true)
JavaClass javaClass = new JavaClass()
when:
javaClass.method()
then:
1 * ClassWithStaticMethod.doSomething() // <--- FAILS
}
}
This fails with message:
Static method called <--- original method is called, it's not mocked
Too few invocations for:
1 * ClassWithStaticMethod.doSomething() (0 invocations)
Unmatched invocations (ordered by similarity):
None
So, static method is not mocked and the actual implementation is always called. Can anyone explain this behaviour? Any idea how to bypass this?
Java version: 1.7.0_79, Groovy version: 2.4.7, Spock version: 1.0-groovy-2.4, cgclib: 3.1
If java codes are compiled with groovyc
def "foo"() {
setup:
// GroovyMock(ClassWithStaticMethod, global: true)
GroovySpy(ClassWithStaticMethod, global: true)
JavaClass javaClass = new JavaClass()
when:
javaClass.method()
then:
// 1 * ClassWithStaticMethod.doSomething()
1 * ClassWithStaticMethod.doSomething() >> null
}
If java codes are compied with javac
1.prepare test code(this sample is MySpock.groovy)
// This Grabs are used for compile.
// These libraries must specifiy on class path when the file executs.
#Grapes([
#Grab(group='org.jmockit', module='jmockit', version='1.8'),
#Grab(group='org.spockframework', module='spock-core', version='1.0-groovy-2.4')
])
import spock.lang.*
import mockit.*
class MySpock extends Specification {
def "hoge"() {
setup:
// Overwrite ClassWithStaticMethod#doSomething(static method) with JMockit/MockUp
new MockUp<ClassWithStaticMethod>() {
#Mock
public static void doSomething() {
Logger.append("abc")
}
}
// Target object for this test
JavaClass javaClass = new JavaClass()
when: "Execute target method"
javaClass.method()
then: "ClassWithStaticMethod#doSomething was mocked and write the value in a file"
Logger.count() == 1
cleanup: "Delete log file for this test"
Logger.delete()
}
}
// Logging Utility for only this test.
class Logger {
static logFile = new File("/tmp/MySpock.groovy.log")
static append = {String msg -> logFile.append("${msg}${System.getProperty("line.separator")}")}
static count = {logFile.readLines()?.size()?:0}
static delete = { logFile.delete() }
}
2.compile codes
javac ClassWithStaticMethod.java&&javac JavaClass.java&&groovyc MySpock.groovy
3.execute test
groovy -cp .:$HOME/.groovy/grapes/org.jmockit/jmockit/jars/jmockit-1.8.jar:$HOME/.groovy/grapes/org.spockframework/spock-core/jars/spock-core-1.0-groovy-2.4.jar MySpock
I have used JMockit at first time.
So, I don't know whether this usage is correct.
I have no idea for method that access and add staic field each other between Spock and Mock(JMockit).
Therefore i created log file to check whether the "ClassWithStaticMethod#doSomething" is called from the "JavaClass#method".
I have two classes that each implement something differently but the tests are the same for both. Each class does some things that would affect the other class if they run in parallel, so they can't run in parallel. (that's the rationale behind the code below)
If you run the class Both, see below, in Eclipse, as a TestNG test, one would expect it to run tests test1 and test2 of class ClassAAA first and then the same test methods for ClassBBB, because ClassBBB's group annotations specify that it depends on ClassAAA's annotation.
However, what you find out is that, seemingly, TestNG has a different way of looking at it, and, "seemingly", it ignores the group order and runs the tests of the two clases in parallel.
class Both {
#Test(groups={"base"})
public static abstract class BothBase {
#Test public void test1() { System.out.println("test1"+name()); }
#Test public void test2() { System.out.println("test2"+name()); }
protected String name() {
String s = getClass().getName();
s = s.substring( 1 + s.lastIndexOf("$"));
return " - " + s;
}
}
#Test(groups={"gr1"})
public static class ClassAAA extends BothBase { }
#Test(groups={"gr2"},dependsOnGroups={"gr1"})
public static class ClassBBB extends BothBase { }
}
The output is:
test1 - ClassAAA
test1 - ClassBBB
test2 - ClassAAA
test2 - ClassBBB
One way, which i don't like, to try to "force" it to honor the desired group order, is to add a dummy test method to the leaf classes, as follows:
#Test(groups={"gr1"})
public static class ClassAAA extends BothBase {
#Test public void dummyTestMustBeInAllLeavesToEnforceGroupOrder() {
System.out.println("dummyTestMustBeInAllLeavesToEnforceGroupOrder"+name());
}
}
#Test(groups={"gr2"},dependsOnGroups={"gr1"})
public static class ClassBBB extends BothBase {
#Test public void dummyTestMustBeInAllLeavesToEnforceGroupOrder() {
System.out.println("dummyTestMustBeInAllLeavesToEnforceGroupOrder"+name());
}
}
This still doesn't completely do what one would expect. The output is:
test1 - ClassAAA
test2 - ClassAAA
test2 - ClassBBB
dummyTestMustBeInAllLeavesToEnforceGroupOrder - ClassAAA
test1 - ClassBBB
dummyTestMustBeInAllLeavesToEnforceGroupOrder - ClassBBB
This means that it started running the tests of ClassBBB before finishing the tests of ClassAAA.
I don't like the fact that i have to add a dummy/unrelated method to each, to get TestNG to understand that they cannot be run in parallel. In fact, i don't care which class runs first... And, i didn't really accomplish what i wanted because they are still running in parallel.
The stupidest way to do this, which would accomplish my goal is to move the tests from the base class to each of the leaf classes - is that how you are suppose to do these things in TestNG?
Is there another way of doing that? i'm sure someone is going to suggest priorities - but again, that does not convey the true intention - i don't have any priority - just don't want them to run in parallel. Also i don't want to write XML files...
This problem is coming due to static inner classes. Try below code you will get required output
import org.testng.annotations.Test;
#Test(groups={"base"})
public abstract class BothBase {
#Test public void test1() { System.out.println("test1"+name()); }
#Test public void test2() { System.out.println("test2"+name()); }
protected String name() {
String s = getClass().getName();
s = s.substring( 1 + s.lastIndexOf("$"));
return " - " + s;
}
}
#Test(groups={"gr1"})
class ClassAAA extends BothBase { }
#Test(groups={"gr2"},dependsOnGroups={"gr1"})
class ClassBBB extends BothBase { }
Many ways
Simplest - priority
Bit harder( groups)
Check testng manual(for ex. this http://www.mkyong.com/tutorials/testng-tutorials/).
I was annoyed to find in the Parameterized documentation that "when running a parameterized test class, instances are created for the cross-product of the test methods and the test data elements." This means that the constructor is run once for every single test, instead of before running all of the tests. I have an expensive operation (1-5 seconds) that I put in the constructor, and now the operation is repeated way too many times, slowing the whole test suite needlessly. The operation is only needed once to set the state for all of the tests. How can I run several tests with one instance of a parameterized test?
I would move the expensive operation to a #BeforeClass method, which should execute just once for the entire parameterized test.
A silly example is shown below:
#RunWith(Parameterized.class)
public class QuickTest {
private static Object expensiveObject;
private final int value;
#BeforeClass
public static void before() {
System.out.println("Before class!");
expensiveObject = new String("Just joking!");
}
#Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] { { 1 }, { 2 } });
}
public QuickTest(int value) {
this.value = value;
}
#Test
public void test() {
System.out.println(String.format("Ran test #%d.", value));
System.out.println(expensiveObject);
}
}
Will print:
Before class!
Ran test #1.
Just joking!
Ran test #2.
Just joking!