#ExtendWith getting executed in every test class, rather than only once - java

I am trying to create extensions A_Extension and B_Extension, which will get executed only once at start and at the end of all test classes.
Where as, I want to call C_Extension always in each test class.
Here are my extensions and test classes.
public class A_Extension implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {
private static boolean isInitialized = false;
#Override
public void beforeAll(ExtensionContext context) throws Exception {
if (!isInitialized) {
//Do something and return ABC
isInitialized = true;
context.getRoot().getStore(GLOBAL).put("ABC", ABC);
}
}
#Override
public void close() throws Throwable {
ABC = null;
}
}
public class B_Extension implements BeforeAllCallback, ExtensionContext.Store.CloseableResource {
private static boolean isInitialized = false;
#Override
public void beforeAll(ExtensionContext context) throws Exception {
if (!isInitialized) {
//Do something and return PQR
isInitialized = true;
context.getRoot().getStore(GLOBAL).put("PQR", PQR);
}
}
#Override
public void close() throws Throwable {
PQR = null;
}
}
public class C_Extension implements AfterEachCallback, AfterAllCallback, BeforeAllCallback {
//some extension code
}
#ExtendWith({A_Extension.class,B_Extension.class})
class TestClass1 {
#RegisterExtension
static C_Extension cExtension = new C_Extension();
#BeforeAll
static void beforeAllClass() { }
#AfterAll
static void afterAllClass() { }
#Test
void case1() { }
#Test
void case2() { }
}
#ExtendWith({A_Extension.class,B_Extension.class})
class TestClass2 {
#RegisterExtension
static C_Extension cExtension = new C_Extension();
#BeforeAll
static void beforeAllClass() { }
#AfterAll
static void afterAllClass() {}
#Test
void case1() {}
#Test
void case2() {}
}
But A_Extension.class and B_Extension.class are getting called always in each test case.
What can be the reason behind this?

Related

How to unit test logic in an inner class using Mockito / Powermockito

I have the following class to test.
public class ClassToTest {
private View view;
public ClassToTest(View view) {
this.view = view;
}
public void init() {
view.add(new ParamClass.OnSomething() {
#Override
public void onSomethingElse() {
view.doSomeWork();
}
});
}
}
Where view is
public class View {
public void add(OnSomething onSomething) {
}
public void doSomeWork() {
}
}
I have mocked view object, but no clue how to test the logic marked "Some logic here to test"
ParamClass is final.
public final class ParamClass {
public interface onSomething {
public void onSomethingElse();
}
}
Without making change to source, is there a way to unit test this using Mockito / Powermockito?
I'm trying to verify the invocation of doSomeWork()
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ClassToTest.class })
public class TestClass {
#Mock View view;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
ClassToTest classToTest = new ClassToTest(view);
PowerMockito.doCallRealMethod().when(view).add(Mockito.any(ParamClass.OnSomething.class));
PowerMockito.whenNew(ParamClass.OnSomething.class)
.withAnyArguments()
.thenReturn(new ParamClass.OnSomething() {
#Override
public void onSomethingElse() {
view.doSomeWork();
}
});
classToTest.init();
Mockito.verify(view, Mockito.times(1)).doSomeWork();
}
}
Its throwing exception
java.lang.ArrayIndexOutOfBoundsException: 0
at org.powermock.api.mockito.internal.expectation.DefaultConstructorExpectationSetup.withAnyArguments(DefaultConstructorExpectationSetup.java:66)
at com.linkedin.android.lite.animations.TestClass.test(TestClass.java:29)
I figured out how to do it. Updating the answer.
public class TestClass {
#Mock View view;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
ClassToTest classToTest = new ClassToTest(view);
classToTest.init();
ArgumentCaptor<ParamClass.OnSomething> captor =
ArgumentCaptor.forClass(ParamClass.OnSomething.class);
verify(view).add(captor.capture());
ParamClass.OnSomething onSomething = captor.getValue();
onSomething.onSomethingElse();
Mockito.verify(view, Mockito.times(1)).doSomeWork();
}
}
Well what are you exactly trying to test? If there is code inside onSomethingElse that calls other objects/methods then you can simply mock all those other calls and then use Mockito.verify(mockObjectHere).methodCalled() on those methods that were called, if you just want to implement testing for behaviour.

Spy an already initialized Java object Mockito

I am using the Mocktio library to write some test cases, since I have an elaborate inhertance structure, I have a few objects which are instantiated in the parent class, and I would like to mock one of its function call. Does Mockito library provide any way to spy on a already initialized object?
Also, the object is not directly instantiable.
Similar to the following -
public class A {
protected static MyObject a;
public static void someMethod() {
a = myObjectBuilder.createObj();
}
}
And another class B looks something similar to
class B extends A {
#BeforeClass
public static void setUpBeforeClass() {
someMethod();
}
#Test
public void mockTest() {
// now mock behavior of some method of MyObject a
// Missing line to spy object a.
Mockito.doReturn(false).when(a).xyz();
/* Now call some method that triggers a.xyz()
again, it is not a direct call,
there are multiple layer of abstraction
*/
}
}
Edit: I have tried the following and it does not work
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
Basically, don't do initialisation in BeforeClass, it runs only once but
you need to have new spy in each test, or you must "reinitialise" spy object
before each test.
Please examine this code:
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import static org.assertj.core.api.Assertions.assertThat;
class MyObject{
public String cos;
public MyObject(String cos) {
this.cos = cos;
}
public boolean xyz() {
return true;
}
}
class A {
protected static MyObject a;
public void someMethod() {
a = new MyObject("cccc");
}
}
public class B extends A {
#Before
public void setUpBeforeTest() {
someMethod();
}
#Test
public void mockTest() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(mock_object.xyz()).isFalse();
}
#Test
public void mockTest2() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(true).when(mock_object).xyz();
assertThat(mock_object.xyz()).isTrue();
}
}
If you want it your way, please change:
public void someMethod() {
a = myObjectBuilder.createObj();
}
into:
public static void someMethod() {
a = myObjectBuilder.createObj();
}
You can't call non static method from static initialiser #BeforeClass:
class A {
protected static MyObject a;
public static void someMethod() {
a = new MyObject("cccc");
}
}
public class B extends A {
#BeforeClass
public static void setUpBeforeClass() {
someMethod();
}
#Test
public void mockTest() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(mock_object.xyz()).isFalse();
}
#Test
public void mockTest2() {
MyObject mock_object = Mockito.spy(a);
// Here we replace original object with our spy
A.a = mock_object;
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(a.xyz()).isFalse();
}
}
Another example (in this case we replace object a with mock (spy is not needed):
class MyObject{
public String cos;
public MyObject(String cos) {
this.cos = cos;
}
public boolean xyz() {
return true;
}
}
class A {
protected MyObject a;
public A() {
a = new MyObject("ggggg");
}
public String doSomethingWithA(){
if(a.xyz()){
return a.cos;
}
else{
return "aaaa";
}
}
}
#RunWith(MockitoJUnitRunner.class)
public class B {
#Mock
MyObject mock_object;
#InjectMocks
A systemUnderTest = new A();
#Test
public void mockTest1() {
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(systemUnderTest.doSomethingWithA()).isEqualTo("aaaa");
}
#Test
public void mockTest2() {
Mockito.doReturn(true).when(mock_object).xyz();
assertThat(systemUnderTest.doSomethingWithA()).isNull();
}
}

Junit testing - Initialization Exception error

//registry Class
public class Registry
{
private static final Logger logger = LogFactory
.getLogger(Registry.class);
protected Service service = new serviceMLImpl();
private static Registry instance = new Registry();
public static Registry getInstance()
{
return instance;
}
public static void setInstance(Registry instance)
{
Registry.instance = instance;
}
public Helper getHelper()
{
return new Helper();
}
}
//Helper Class
public class Helper
{
protected Service service = ServiceRegistry
.getService();
public Helper()
{
}
public void sendInfo(Info info)
throws Exception
{
service.sendInfo(info);
}
public void sendFacilitySFPListNotification(
List<GcpFacilitySFPInfo> esfpPortList)
{
gfpGcpService.sendFacilitySFPListNotification(esfpPortList);
}
}
//Test Class
public class RegistryTest
{
Registry registry = new Registry();
Helper helper = createMock(Helper.class);
#Before
public void setUp() throws Exception
{
}
#After
public void tearDown() throws Exception
{
registry = null;
}
#Test
public void testGetInstance()
{
replayAll();
registry.getInstance();
verifyAll();
}
#Test
public void testSetInstance()
{
replayAll();
registry.setInstance(registry);
verifyAll();
}
#Test
public void testGetHelper()
{
**replayAll();
new Helper();
registry.getHelper(); // getting InitializationExceptionError here
verifyAll();** //
}
}
Two classes are there, Helper and Registry class. I tried to write the junit for registry class but got InitializationException in the test class.
This is the error i am getting at registry.getHelper():
java.lang.ExceptionInInitializerError at java.lang.Class.forName0(Native Method) at
java.lang.Class.forName(Class.java:169) at
javassist.runtime.Desc.getClassObject(Desc.java:44) at
javassist.runtime.Desc.getClassType(Desc.java:153) at
javassist.runtime.Desc.getType(Desc.java:123) at
javassist.runtime.Desc.getType(Desc.java:79) at
com.att.bbnms.cim.gfpgcp.service.ServiceRegistry.getService(ServiceRegistry.java‌​:41) at
com.att.bbnms.cim.nc.service.link.Helper.(Helper.java:14) at
com.att.bbnms.cim.nc.service.link.Registry.getHelper(Registry.java:26) at
com.att.bbnms.cim.nc.service.link.egistryTest.testGetHelper(RegistryTest.java:63‌​) at
org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66) at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$Po‌​werMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:‌​312) at
org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86) at
org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadi‌​e.java:94) at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$Po‌​werMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:29‌​6) at
Also while writing the test case for Helper , I am not able to get in the class.
Please tell if you have any solution.

Use old instance in JUnit test

I try to use different instances for my tests but the first one is always used.
During the second test, it's the content of the first instance that is displayed.
I don't know where to look for.
public class MyActivityTest extends
ActivityInstrumentationTestCase2<MyActivity> {
private Solo solo;
public MyActivityTest() {
super(MyActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
Authentication.setSessionId("mysessionid", this.getInstrumentation()
.getTargetContext().getApplicationContext());
solo = new Solo(getInstrumentation(), getActivity());
}
public void testFailFetching() {
CommunicationFactory.setInstance(MyActivityData.FALSE_QUIZCOMM_DEFAULT);
//some Solo tests
}
public void testSucceedFetching() {
CommunicationFactory.setInstance(MyActivity.CORRECT_QUIZCOMM_DEFAULT);
//some Solo tests
}
#Override
protected void tearDown() throws Exception {
CommunicationFactory.setInstance(null);
super.tearDown();
}
}
The setUp() method will be called before each test. Provided it completes without throwing an exception (which presumably would abort your tests anyway), your solo variable is being reconstructed for each test. The follow test code demonstrates this:
public class ExampleTest extends TestCase {
private static int num = 1;
private Foo foo;
#Override
protected void setUp() throws Exception {
super.setUp();
foo = new Foo(num++);
}
public void testA() {
foo.printNum();
}
public void testB() {
foo.printNum();
}
private static class Foo {
private final int num;
public Foo(int num) {
this.num = num;
}
public void printNum() {
System.out.println(num);
}
}
}
This prints:
1
2
It's possible the Solo objects equal each other in the separate tests. But they won't be the same object.

Running two same tests with different arguments

I have a test with 15-20 different test cases, I want to run the same test with twice with two different parameters which are supposed to be passed to the test's BeforeClass method, for instance:
public class TestOne {
private static ClassToTest classToTest;
#BeforeClass
public static void setUp() throws Exception {
classToTest = new ClassToTest("Argument1", "Argument2");
}
#Test
public void testOne() {
........roughly 15 - 20 tests here
}
public class TestTwo {
private static ClassToTest classToTest;
#BeforeClass
public static void setUp() throws Exception {
classToTest = new ClassToTest("Argument3", "Argument4");
}
#Test
public void testOne() {
........roughly 15 - 20 tests here, same as in TestOne
}
As you can see the only difference between these two tests is in the setup method, which passes different values to the constructor of the ClassToTest. I don't want to replicate the test methods in both classes, but would prefer either inheritance or some other intelligent way to achieve this in one class.
This seems like a perfect use case for JUnit4's #Parameters; see https://blogs.oracle.com/jacobc/entry/parameterized_unit_tests_with_junit or http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/ . That said, you'll have to move the initialization from the setUp method to a constructor for the test class.
For what it's worth, here is how you would do it with TestNG:
public class TestFactory {
#Factory
public Object[] createTests() {
return new Object[] {
new ClassToTest("arg1", "arg2"),
new ClassToTest("arg3", "arg4")
};
}
}
public class ClassToTest {
public ClassToTest(String arg1, String arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
#Test
public void testOne() {
// use arg1 and arg2
}
}
Thanks all for your quick replies. This is how I did it finally
public abstract class Base {
final HeavyObject heavy;
protected Base(HeavyObject heavy) {
this.param = param;
}
#Test
public void test() {
param.doSomething();
}
#Test
.............More tests here
}
public class FirstTest extends Base{
private static HeavyObject param;
#BeforeClass
public static void init() {
param = new HeavyObject("arg1", "arg2");
}
public FirstTest() {
super(param);
}
}
public class SecondTest extends Base{
private static HeavyObject param;
#BeforeClass
public static void init() {
param = new HeavyObject("arg3", "arg4");
}
public FirstTest() {
super(param);
}
}
Base is an abstract class which has all the tests and FirstTest and SecondTest create their own objects with different parameters and pass it to the abstract class to use it.
As per the documentation (http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html):
A subclass does not inherit the private members of its parent class.
However, if the superclass has public or protected methods for
accessing its private fields, these can also be used by the subclass.
How about this:
public class TestOne {
private static ClassToTest classToTest1, classToTest2;
#BeforeClass
public static void setUp() throws Exception {
classToTest1 = new ClassToTest("Argument1", "Argument2");
classToTest2 = new ClassToTest("Argument3", "Argument4");
}
#Test
public void testOne() {
testOneImpl(classToTest1);
testOneImpl(classToTest2);
}
public void testOneImpl(ClassToTest classToTest) {
// exact samew as whatever your current testOne() test method is
}
....
}
EDIT:
Or to keep method count down:
public class TestOne {
private static List<ClassToTest> classesToTest;
#BeforeClass
public static void setUp() throws Exception {
classesToTest = new ArrayList<>;
classesToTest.add( new ClassToTest("Argument1", "Argument2"));
classesToTest.add( new ClassToTest("Argument3", "Argument4"));
}
#Test
public void testOne() {
for (ClassToTest classToTest: classesToTest) {
... same test content as before
}
}

Categories

Resources