Is it possible to define Cucumber test step definition in Java interface? - java

I want to define Cucumber test steps definition in Java interface.
public interface ITestSteps {
#Before
public void setUpLocal() throws Throwable;
#When("^Landing screen is visible$")
public void Landing_Screen_is_visible() throws Throwable;
}
2 other classes will implement this interface:
public class AppleTestSteps implements ITestSteps { ... }
public class AndroidTestSteps implements ITestSteps { ... }
I have TestFactory class that get property with enviroment name (Android or Apple) and initialize object:
ITestSteps steps = TestFactory(platformName);
Problem: Cucumber takes needed step by name, without reference to the object. Takes Landing_Screen_is_visible() not a steps.Landing_Screen_is_visible()
Is it possible to implement interface before Cucumber try to find need step by name? Make static?
Or may be there is another way of implementation Cucumber steps? (Same steps but different implementation)

what your looking for is the driver pattern where you have the same steps defs but use a different application driver when used in different test environments example
abstract class MyApplicationDriver {
abstract void login();
then implementation for Android
class AndriodApplicationDriver extends MyApplicationDriver {
void login(){};
and then another
class AppleTestDriver extends MyApplicationDriver {
void login(){};
use the MyApplicationDriver as the interface in the tests and then use the implementation in the context , you have to look at the World object on how to do this

Related

Get around early binding of static methods in java

I have a AbstractBaseRepository. All my Repositories extends from this class. I created another class RepositoryFactory to create any instance of Repository. Due to early binding of static method, I am facing problem.
public abstract class AbstractBaseRepository {
public static <T extends AbstractBaseRepository> T getNewInstance(EntityManagerFactory entityManagerFactory) {
throw new RuntimeException("Override and provide valid initialization");
}
...
}
public class RepositoryFactory {
public static <T extends AbstractBaseRepository> T getRepository(Class<T> cls) {
return T.getNewInstance(entityManagerFactory);
}
...
}
an example subclass
public class DeviceModelRepo extends AbstractBaseRepository {
public static DeviceModelRepo getNewInstance(EntityManagerFactory entityManagerFactory) {
return new DeviceModelRepo(entityManagerFactory);
}
...
}
Whenever I call getRepository() with a valid subclass of AbstractBaseRepository, runtime exception is thrown. This is due to early binding of static methods. During compile time, getNewInstance gets bound with AbstractBaseRepository rather than at runtime with actual type of the class. Any good workarounds?
My first suggestion is using Spring. It is very easy to get a list of all beans created with a certain interface.
Also, if you think of your Repository instances as a type of "plug-in" you might see how Java's ServiceLoader class can help.
Also, another approach is to use a switch statement in the factory and create the instances for each case rather than using static methods on the Repository subclasses.
Finally, I don't recommend reflection solutions but there are ways to load the class based on its name and reflectively creating a new instance.
But overriding static methods is not possible.
What I have understood by seeing your code is that you want to have different implementations of AbstractBaseRepository such as DeviceModelRepo. Then you want a factory class to create the instance of specific implementation of AbstractBaseRepository. Here the major problem is you try to overriding static methods which can never be overwritten but subclass will hide the parent implementation. Please don't use static method for overriding. You can change your implementation as given below and this issue will be resolved.
public abstract class AbstractBaseRepository {
public AbstractBaseRepository(EntityManagerFactory entityManagerFactory){
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Then below implementation for subclass.
public class DeviceModelRepo extends AbstractBaseRepository {
public DeviceModelRepo(EntityManagerFactory entityManagerFactory) {
super(entityManagerFactory);
...
}
//removed method getNewInstance(EntityManagerFactory entityManagerFactory)
...
}
Now I am providing you two implementation of factory class.
One is having different method for each of implementation, such as getDeviceModelRepository().
Another solution is to use reflection and get repository instance by passing the implementation repository class.
public class RepositoryFactory {
//Solution-1, create separate method for each of repository like below
public static AbstractBaseRepository getDeviceModelRepository() {
return new DeviceModelRepo(entityManagerFactory);
}
//Solution-2, use reflection to get instance of specific implementation
//of AbstractBaseRepository
public static <T extends AbstractBaseRepository> T
getRepository(Class<T> repoClass) throws Exception{
return repoClass.getConstructor(EntityManagerFactory.class)
.newInstance(entityManagerFactory);
}
...
}
With reflection solution, you can get the repository instance as given below.
RepositoryFactory.getRepository(DeviceModelRepo.class)

Annotation - how to add field level annotation in Java dynamically

Imagine there is class
public class sample {
private String fieldName;
}
Which already compiled and the part of the claspath when the jam statsup.
I want add #notnull and #size(min=1,max=5) dynamically for fieldName(not class level)
Any suggestions plz
I'll try to answer the question as a ByteBuddy question, without the synopsis of validation.
Using ByteBuddy, you can change your classes at runtime. But in certain conditions, like you are not on Android (Dalvik's virtual machine is different than ordinary JVMs), and you shouldn't change an already loaded class.
class Subclass {
public void func() {
}
}
class FunctionalInterfaceImpl implements FunctionalInterface {
#Override
public Class<? extends Annotation> annotationType() {
return FunctionalInterface.class;
}
}
public class TryingByteBuddy {
public static void main(String[] args) {
new ByteBuddy()
.redefine(TypePool.Default.ofClassPath().describe("com.experiments.Subclass").resolve(),
ClassFileLocator.ForClassLoader.ofClassPath())
.annotateType(new FunctionalInterfaceImpl())
.make()
.load(ClassLoader.getSystemClassLoader());
System.out.println(Arrays.deepToString(new Subclass().getClass().getAnnotations()));
}
}
In this code Subclass is a class that doesn't have the #FunctionalInterface annotation. Now when you run you will find it has it.
NOTES ON THIS CODE:
You will find that we didn't use Subclass.class when trying to redefine the class
This is to prevent loading of the class before creating the alternative
Using Subclass.class will invoke the class loader to load the original class, this prevents ByteBuddy from doing its work
We "implemented" the annotation interface we want to add (FunctionalInterface in this example).
For more info:
ByteBuddy tutorial

How To Write Test case for Java Interface which extends Java frame work interface

I have a interface where my interface extends the spring PagingAndSortingRepository. I want to write unit test case. How can I write unit test case for this.
public interface LookUpRepository extends PagingAndSortingRepository<Lookup, Long> {
public List<Lookup> findAll();
}
can some body help .........
Thanks in advance.
So because this class is an interface, it doesn't have any internal logic. As a result, it doesn't really make sense to unit test it. Instead, you should unit test the implementations of the interface.
A pattern which I have seen is to define a set of unit tests on the interface and then extend that unit test for each implementation. This makes sure that the implementations all adhere to the interface.
public abstract class LookUpRepositoryTest {
public abstract LookUpRepository getRepository();
// ... your tests ...
}
public MyLookUpRepositoryTest extends LookUpRepositoryTest {
#Override
public LookUpRepository getRepository() {
return new MyLookUpRepository();
}
}
As I'm looking at your code, it appears to be using Spring data. If this is the case, you will need to look at Spring unit testing.

How can we test that a class implements many interfaces?

My question is about testing a class that implements many interfaces. For example, I have this class:
public class ServiceControllerImpl extends ServiceController implements IDataChanged, IEventChanged {
}
Now there are two ways for testing. The first is testing directly on the concrete class. That means the object type is the concrete class rather than the interface.
public class ServiceControllerImplTest {
ServiceControllerImpl instance;
#Before
public void setUp() {
instance = new ServiceControllerImpl();
// you can bring this instance anywhere
}
}
The second way is testing on the interface only. We must typecast this object to all interfaces it implements.
public class ServiceControllerImplTest {
ServiceController instance; // use interface here
IDataChanged dataChangeListener;
#Before
public void setUp() {
instance = new ServiceControllerImpl();
dataChangeListener = (IDataChanged) instance;
// instance and dataChangeListener "look like" two different object.
}
}
I prefer the second solution because maybe in future we can change the interface it implements to other objects, so using the concrete class might lead to failing tests in the future. I don't know the best practice for this problem.
Thanks :)
I prefer second solution because in reality, maybe in future we can change the interface it implements to other objects, so force using concreted class maybe leads to fail test in the future.
I guess it will lead to failed tests anyway, because you usually test that assertions are true or false. The question is: Do that tests apply to any IDataChanged or do these assertions only apply to the ServiceControllerImpl?
If the assertions only apply to the ServiceControllerImpl it doesn't matter if you use an IDataChanged instead of an ServiceControllerImpl, because you must edit the test when you use another IDataChanged object - different assertions. The test will fail if you use another object.
The way you setup unit tests Itself gives you an answer. A unit test usually tests one class in isolation. This means that you mock the environment. But mocking the environment means that you know the dependencies of the class you test and this are implementation details. So your test is written on an implemtation basis rather than only the interface.
It's possible to write tests that only test an abstract api - like an interface. But this usually means that your tests are abstract too. E.g.
public abstract class SetTest {
#Test
public void addAlreadyExistentObject(){
Set<String> setUnderTest = createSetUnderTest();
Assert.assertTrue(setUnderTest.isEmpty());
boolean setChanged = setUnderTest.add("Hello");
Assert.assertTrue(setChanged);
setChanged = setUnderTest.add("Hello");
Assert.assertFalse(setChanged);
Assert.assertEquals(setUnderTest.size(), 1);
}
protected abstract Set<String> createSetUnderTest();
}
You can then extend these abstract tests to test the api for concrete classes. E.g.
public class HashSetTest extends SetTest {
#Override
protected Set<String> createSetUnderTest() {
return new HashSet<String>();
}
}
In this case you can replace the implementation and the test must remain green.
But here is another example of an abstract api when replacing the object under test does not really make sense.
What about writing a test for all Runnables?
public class RunnableTest {
#Test
public void run(){
Runnable runnable = ...;
// What to test here?
// run is invoked without throwing any runtime exceptions?
runnable.run();
}
}
As you can see it does not make sense in some cases to write tests in a way so that you can easily replace the object under test.
If an api like the Set api defines a concrete state handling you can write abstract tests that test this.
JayC667 already correctly answered that it's best to refer to a class through its supertype(s) in tests of methods defined by those types. But I'd change the way you did that a bit to avoid casting:
public class ServiceControllerImplTest {
ServiceController controller;
IDataChanged dataChangeListener;
#Before
public void setUp() {
instance = new ServiceControllerImpl();
controller = instance;
dataChangeListener = instance;
}
}

TestNg, annotation "beforeTestMethod" and override

For my tests I'm using a base class MyTestBase defining a method setup() that does some base preparations:
public class MyTestBase {
#Configuration( beforeTestMethod=true )
protected void setup() {
// do base preparations
}
}
Now I have some more specific test classes that have to do their own preparations. There are different ways how to implement this.
I could use #Override:
public class MySpecialTestBase extends MyTestBase {
#Override
protected void setup() {
super.setup();
// do additional preparations
}
}
...or I could use a separate setup method:
public class MySpecialTestBase extends MyTestBase {
#Configuration( beforeTestMethod=true )
protected void setupSpecial() {
// do additional preparations
}
}
Is there a prefered way to implement this?
I would prefer using #Configuration annotation. #Override and super are more fragile. You can forget to call super.setup(), or call it in wrong place. Meanwhile, using separate method with #Configuration lets you to choose more appropriate naming for child setup method if necessary, and you get setup order guaranteed by TestNG (parent then child).
Two more points:
I'd make parent setup final in order to forbid accidental overriding.
I'd use #BeforeMethod annotations. They are available since TestNG 5.0. Of course, for older versions you forced to using #Configuration.

Categories

Resources