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;
}
}
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
I have simple test case:
#Test
public void test() throws Exception{
TableElement table = mock(TableElement.class);
table.insertRow(0);
}
Where TableElement is GWT class with method insertRow defined as:
public final native TableRowElement insertRow(int index);
When I launch test I'm getting:
java.lang.UnsatisfiedLinkError: com.google.gwt.dom.client.TableElement.insertRow(I)Lcom/google/gwt/dom/client/TableRowElement;
at com.google.gwt.dom.client.TableElement.insertRow(Native Method)
Which as I believe is related with insertRow method being native. Is there any way or workaround to mock such methods with Mockito?
Mockito itself doesn't seem to be able to mock native methods according to this Google Group thread. However you do have two options:
Wrap the TableElement class in an interface and mock that interface to properly test that your SUT calls the wrapped insertRow(...) method. The drawback is the extra interface that you need to add (when GWT project should've done this in their own API) and the overhead to use it. The code for the interface and the concrete implementation would look like this:
// the mockable interface
public interface ITableElementWrapper {
public void insertRow(int index);
}
// the concrete implementation that you'll be using
public class TableElementWrapper implements ITableElementWrapper {
TableElement wrapped;
public TableElementWrapper(TableElement te) {
this.wrapped = te;
}
public void insertRow(int index) {
wrapped.insertRow(index);
}
}
// the factory that your SUT should be injected with and be
// using to wrap the table element with
public interface IGwtWrapperFactory {
public ITableElementWrapper wrap(TableElement te);
}
public class GwtWrapperFactory implements IGwtWrapperFactory {
public ITableElementWrapper wrap(TableElement te) {
return new TableElementWrapper(te);
}
}
Use Powermock and it's Mockito API extension called PowerMockito to mock the native method. The drawback is that you have another dependency to load into your test project (I'm aware this may be a problem with some organizations where a 3rd party library has to be audited first in order to be used).
Personally I'd go with option 2, as GWT project is not likely to wrap their own classes in interfaces (and it is more likely they have more native methods that needs to be mocked) and doing it for yourself to only wrap a native method call is just waste of your time.
In case anybody else stumbles about this: In the meantime (in May 2013) GwtMockito turned up, which solves this problem without PowerMock's overhead.
Try this
#RunWith(GwtMockitoTestRunner.class)
public class MyTest {
#Test
public void test() throws Exception{
TableElement table = mock(TableElement.class);
table.insertRow(0);
}
}
We have DAO tests that should run against both the real DAO/database, and against a mock dao to verify that the mock dao behaves the same as the real dao. To this end, we have a structure like this:
public abstract class DAOTestBase
{
public void testSimple()
{
// dummy assertion
assertTrue(true, "Hello");
}
}
#Test(groups = "fast")
public class TestMockDAO extends DAOTestBase
{
// setUp/tearDown and helper methods for mock
}
#Test(groups = "slow")
public class TestDAO extends DAOTestBase
{
// setUp/tearDown and helper methods for real DB
}
Unfortunately this doesn't work - TestNG doesn't think that the testSimple method is a test and hence won't run it. So instead I tried to annotate the testSimple method (or the DAOTestBase class):
A #Test annotation without any groups will lead to the same effect - the test won't run for either fast nor slow groups.
A #Test annotation with groups fast and slow will lead to the opposite effect - both TestMockDAO and TestDAO will be run regardless of whether only fast or only slow tests should be run.
A #Test annotation with a different group, say common, plus added dependsOnGroups="common" annotations in both TestMockDAO and TestDAO will also not work unless common is included in the groups to run which leads again to case 2 above (both TestMockDAO and TestDAO are run).
In the end, what I'm looking for is a way to be able to define the group for the inherited tests in the sub class, but it seems as if the #Test annotation is only applied to test methods in that very same class, not also to inherited methods that don't have a #Test annotation. Is there any other way to achieve this (without overriding all methods in the sub classes) ?
I am currently working through a similar situation.
A way to make test cases run is to use something like:
#Test
public void someTest() {
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { SomeTests.class });
testng.run();
}
Reference: http://testng.org/doc/documentation-main.html#running-testng-programmatically
Unforunately I am currently unable to get it to report the test cases within SomeTests.
Have you tried simply adding a #Test annotation on top of DAOTestBase? Each subclass will override it with its own group and this should make the method in the base a test method.
I am using TestNG 6.14.3 version and I found a solution using priority annotation.
Example:
I have a base test class:
public class TestBase {
#Test(priority = 0)
public void testA() {
assertTrue(true, "testA");
}
}
And another extended test class:
public class Test2 extends TestBase {
#Test(priority = 1)
public void testB() {
assertTrue(true, "testB");
}
}
When I run Test2 test class, I obtain the following esult:
testA: true
testB: true
I solved it this way:
The methods in the base class are in "base" group, but need to check if the test have been initialized.
public abstract DaoTestBase {
private boolean initialized = false;
#Test(groups = "base")
public void testSimple() {
if (!initialized) { return; }
// dummy assertion
assertTrue(true, "Hello");
}
}
The test is initialized in the child, in the BeforeClass annotated method.
#BeforeClass
protected void initialize() {
super.initialized = true;
}
If you annotate the parent class instead of the methods, you must pass inheritGroups=false and the group, since it inherits also the group of the base class and it will not work.
Now, you must run TestNG to check groups base,fast or base,slow. Both tests will be executed, but the one not initialized will do nothing.
It is ugly, and I would not recommend it (it looks better to redefine the methods in child and call the according super method), but in my case I need priority in my test methods, and I want to avoid that repetition in each child class.
I have an abstract base class, which I use as a base for my unit tests (TestNG 5.10). In this class, I initialize the whole environment for my tests, setting up database mappings, etc. This abstract class has a method with a #BeforeClass annotation which does the initialization.
Next, I extend that class with specific classes in which I have #Test methods and also #BeforeClass methods. These methods do class-specific initialization of the environment (e.g. put some records into the database).
How I can enforce a specific order of the #BeforeClass annotated methods? I need the ones from the abstract base class to be executed before the ones of the extending class.
Example:
abstract class A {
#BeforeClass
doInitialization() {...}
}
class B extends A {
#BeforeClass
doSpecificInitialization() {...}
#Test
doTests() {...}
}
Expected order:
A.doInitialization
B.doSpecificInitialization
B.doTests
Actual order:
B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization // <---not executed
B.doTests) // <-/
edit: Answer below is for JUnit, but I will leave it here anyway, because it could be helpful.
According to the JUnit api: "The #BeforeClass methods of superclasses will be run before those the current class."
I tested this, and it seems to work for me.
However, as #Odys mentions below, for JUnit you need to have the two methods named differently though as doing otherwise will result in only the subclass method being run because the parent will be shadowed.
Don't put the #BeforeClass on the abstract class. Call it from each subclass.
abstract class A {
void doInitialization() {}
}
class B extends A {
#BeforeClass
void doSpecificInitialization() {
super.doInitialization();
}
#Test
void doTests() {}
}
Seems like TestNG has #BeforeClass(dependsOnMethods={"doInitialization"}) - give it a try.
I added public to the abstract class and TestNG (6.0.1) executed the doInitialization() before doTests. TestNG does not execute doInitialization() if I remove public from class A.
public abstract class A {
#BeforeClass
doInitialization() {...}
}
class B extends A {
#Test
doTests() {...}
}
I just tried your example with 5.11 and I get the #BeforeClass of the base class invoked first.
Can you post your testng.xml file? Maybe you are specifying both A and B there, while only B is necessary.
Feel free to follow up on the testng-users mailing-list and we can take a closer look at your problem.
--
Cedric
I've just gone through this and found one more way to achieve this. Just use alwaysRun on #BeforeClass or #BeforeMethod in the abstract class, works as you would expect.
public class AbstractTestClass {
#BeforeClass(alwaysRun = true)
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
}
For JUnit:
As #fortega has mentioned:
According to the JUnit api: "The #BeforeClass methods of superclasses will be run before those the current class."
But be careful not to name both methods with the same name. Since in this case the parent method will be hidden by child parent. Source.
When I run from: JUnitCore.runClasses(TestClass.class);
It will execute the parent properly, before the child (You do not need super.SetUpBeforeClass();)
If you run it from Eclipse:
For some reason it fails to run the base class.
The work around:
Call the base class explicitely: (BaseTest.setUpBeforeClass();)
You may want to have a flag in the base class in case you run it from an application, to determine if it is already setup or not. So it only runs once if you run it via both possible methods (such as from eclipse for personal testing, and through ANT for a build release).
This appears to be a bug with Eclipse, or at least unexpected results..
How about having your #BeforeClass method call an empty specificBeforeClass() method that may or may not be overwritten by sub classes like so:
public class AbstractTestClass {
#BeforeClass
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
protected void specificBeforeClass() {}
}
public class SpecificTest {
#Override
protected void specificBeforeClass() {
// Do specific stuff
}
// Tests
}
dependsOnMethod can be used.
e.g. in case of Spring (AbstractTestNGSpringContextTests)
#BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
Check your import statement.
It should be
import org.testng.annotations.BeforeClass;
not
import org.junit.BeforeClass;
This works for me --
abstract class A {
#BeforeClass
doInitialization() {...}
}
class B extends A {
#Override
#BeforeClass
doInitialization() {
//do class specific init
}
#Test
doTests() {...}
}
Why don't you try to create an abstract method doSpecialInit() in your super class, called from your BeforeClass annotated method in superclass.
So developpers inheriting your class is forced to implement this method.
There is another easy solution here.
My particular situation is that I need to inject mock services from "BeforeClass" in the subclass before "BeforeClass" in the superclass is executed.
To do this - simply use a #ClassRule in the subclass.
For example:
#ClassRule
public static ExternalResource mocksInjector = new ExternalResource() {
#Override
protected void before() {
// inject my mock services here
// Note: this is executed before the parent class #BeforeClass
}
};
I hope this helps. This can effectively execute static setup in "reverse" order.
I've faced a similar issue today, the only difference was a Base class was not abstract
Here's my case
public class A {
#BeforeClass
private void doInitialization() {...}
}
public class B extends A {
#BeforeClass
private void doSpecificInitialization() {...}
#Test
public void doTests() {...}
}
It occurred that a #BeforeClass method from class A was never executed.
A.doInitialization() -> THIS WAS NEVER EXECUTED silently
B.doSpecificInitialization()
B.doTests()
Playing with privacy modifiers I found that TestNG will not execute a #BeforeClass annotated method from inherited class if a method is not visible from a class-inheritor
So this will work:
public class A {
#BeforeClass
private void doInitialization() {...}
}
public class B extends A {
#BeforeClass
//Here a privacy modifier matters -> please make sure your method is public or protected so it will be visible for ancestors
protected void doSpecificInitialization() {...}
#Test
public void doTests() {...}
}
As a result following happens:
A.doInitialization()
B.doSpecificInitialization()
B.doTests()
In my case (JUnit) I have the same methods called setup() in the base class and the derived class. In this case only the derived class's method is called, and I have it call the base class method.
A better and cleaner way to achieve this using inheritance may be as following -
abstract class A {
#BeforeClass
void doInitialization() {}
}
class B extends A {
#Override
#BeforeClass
void doInitialization() {
super.doInitialization();
}
#Test
void doTests() {}
}