Spring AbstractTransactionalDataSourceSpringContextTests - Preventing database rollback after each Junit test - java

I have a test class that extends AbstractTransactionalDataSourceSpringContextTests.
I did not write this class, and need to make a small change. I'd like to see what would happen if i prevented the recreation of the test database (using DbUnit) after each test.
I have tried playing with the following lines:
#Override
protected void onSetUpBeforeTransaction() throws Exception {
initialisingTables.create("Init");
}
#Override
protected void onTearDownAfterTransaction() throws Exception {
deleteTables(true);
deleteTables(false);
}
But nothing seems to help.

I guess you just have to annotate your test methods with
#Rollback(false)
or the test class with sometjing like this:
#TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
See: 10.3.3. JDBC Testing Support

Related

Close browser after several test classes

I work on an automated testing framework and I need to close the browser after passing tests on several test classes.
The package structure of the project is similar to this:
PackageA
SomeTestClass1
SomeTestClass2
...
PackageB
SomeOtherTestClass1
SomeOtherTestClass2
...
Note: There can be multiple levels of packages inside one another.
If I use #AfterClass or #AfterAll JUnit annotations I have to close the browser at the 'end' of each test class.
My framework requires launching the browser (as a static variable) and closing it only one time to speed up execution and avoid losing time for every browser launch and login, as I currently have a big number of tests that need to be run each night.
Is there any possiblity I could achieve this behaviour?
In JUnit 4, you could use the concept of Rule in conjunction with extending TestWatcher abstract class (org.junit.rules.TestWatcher).
Hence you won't have to close the browser in a method annotated with #AfterClass.
e.g.
public class StartFinishTestWatcher extends TestWatcher {
#Override
protected void starting(Description description) {
System.out.println("Starting test: " + description.getDisplayName());
}
#Override
protected void finished(Description description) {
System.out.println("Finishing test: " + description.getDisplayName());
// close the browser here
}
}
Then you would use this class in a RuleChain, in the test class(es) where you want to close the browser.
public class MyTestInWhichIWantBrowserToClose {
#Rule
public RuleChain ruleChain = buildTestRuleChain();
private RuleChain buildTestRuleChain() { // could be made protected and put in a superclass
return RuleChain.outerRule(new StartFinishTestWatcher());
}
}
In JUnit 5 you could create custom Test Suites and implement BeforeTestExecutionCallback and (in your case) AfterTestExecutionCallback interfaces in one of your base class.
You would then implement the custom logic which decides to close the browser in method public void afterTestExecution(ExtensionContext context).

Spring Junit Database rollback at the end of test class

I have a lot of existing Spring JUnit tests.
All this tests extends an abstract test class.
public class ServiceTest extends AbstractServiceTest {
But in this abstract class we reinitialize the database. So it will reinitialize the database on each test class
#Before
#Override
public void initGlobal() throws Exception {
initDatabase();
... }
I am asking how I can do a rollback on a test class in the end of execution of its tests ? So i can initialize a database one time and rollback changes in every test class
I think having two profiles is a better option one for testing and other one for development and on the testing profile use memory based database like H2 (here is a good example) and on your development profile use your main database
When running the tests use the testing profile.Instead of doing rolling back or deleting data each time you run your test
If you want to use a real database in unit tests that I totally discourage it.You can use the spring test runner to annotate your class and rollback transactions
#RunWith(SpringJUnit4ClassRunner.class)
#TransactionConfiguration(defaultRollback=true)
public class YourTestClass {
#Test
#Transactional
public void myTestMethod() {
// db will get rolled back at the end of the test
}
}

JUnit android test classinheritance

I have simple Android application with some espresso tests.
I want to write some base class so all of my test classes will inherit its #beforeClass and #afterClass methods, but the problem is when I do it like code example below, JUnit doesn't see any tests at al. I got Empty test suite. message. What's the problem?
Code example:
public class RealmTest {
protected static Realm realm;
#BeforeClass
public static void beforeClass() {
realm = Realm.getDefaultInstance();
realm.setAutoRefresh(true);
}
#AfterClass
public static void afterClass() {
realm.close();
}
}
#RunWith(AndroidJUnit4.class)
public class MainActivityTest extends RealmTest {
#Rule
public IntentsTestRule<MainActivity> activityTestRule = new IntentsTestRule<>(MainActivity.class);
#Test
public void startedFine() {
assertNotNull(realm);
onView(withId(R.id.button)).perform(click());
intended(hasComponent(new ComponentName(getTargetContext(), EducationActivity.class)));
}
}
If I'll run all tests, tests from MainActivityTest won't run.
Thanks for your help, pls say if some additional info is needed.
Guessing: the JUnit environment is not looking for static methods. So maybe you simply drop that keyword from your base methods (guess you could keep your Realm static nonetheless; I assume you really only want one of those).
But then, another suggestion: don't use inheritance for test cases.
The point that makes test cases valuable to you is: they should quickly allow you to find and fix bugs in your production code.
But when your "setup" is hidden from your testcases - because things are not only happening in some #Before method ... but in a #Before method somewhere, in some different class ... well, that can seriously increase the time you will need to understand a failing testcase. Because: instead of just studying your test case, you find yourself digging around within test code in order to understand what exactly is happening besides the code in that failing test method itself!
Thus: be really careful to balancing "code duplication" versus "test case is easy to understand" aspects!

Creating custom rollback method EJB3

I'm using EJB3.1 in my application which is running on JBoss AS 6. I'm working as integration developer and I have use case where as part of my transaction there are multiple calls to various external systems via REST, SOAP etc. If any of these calls throw exception I have to rollback changes to previously called systems.
Currently I'm having situation:
public class SystemAException extends RuntimeException {...}
public class SystemBException extends RuntimeException {...}
public class SystemCException extends RuntimeException {...}
System classes
public class SystemA{
public static makeChanges() throws SystemAException{...}
public static cancelChanges() {...}
}
public class SystemB{
public static makeChanges() throws SystemBException{...}
public static cancelChanges() {...}
}
public class SystemC{
public static makeChanges() throws SystemCException{...}
public static cancelChanges() {...}
}
Call
static makeChanges(Object o){
persist(o); //DB work
try {
SystemA.makeChange();
SystemB.makeChange();
SystemC.makeChange();
} catch(SystemBException eb){
SystemA.cancelChanges();
throw eb;
} catch(SystemCException ec){
SystemA.cancelChanges();
SystemB.cancelChanges();
throw ec;
}
update(o); //more DB work
}
I would like to get rid off try-catch and to instruct JBoss to call method cancelChanges() whenever RuntimeException occurs like it does when it rollback changes made to DB.
I'm aware that I could use Commander pattern to undo previously made changes, but I would like to know if container can do that for me.
If it is possible, I would like to accomplish following thing
static makeChanges(Object o){
persist(o); //DB work
SystemA.makeChange();
SystemB.makeChange();
SystemC.makeChange();
update(o); //more DB work
}
If you're calling non-XA external systems via REST/SOAP, what happens if your JVM/network crashes before you can undo the changes? That sounds like a fragile architecture.
Regardless, ther is no way to get the EJB container to do this for you automatically. The best idea I have is to have SystemA/SystemB/SystemC call TransactionSynchronizationRegistry.registerInterposedSynchronization, and then you can be notified when the transaction is rolling back (since the EJB container will roll back transactions automatically if a system exception or application with rollback=true is thrown), and then you can try to undo whatever. Of course, if the JVM crashes then your interposed synchronization listeners will be lost and you can't undo, so it still doesn't solve that problem.

Run unit tests only on Windows

I have a class that makes native Windows API calls through JNA. How can I write JUnit tests that will execute on a Windows development machine but will be ignored on a Unix build server?
I can easily get the host OS using System.getProperty("os.name")
I can write guard blocks in my tests:
#Test public void testSomeWindowsAPICall() throws Exception {
if (isWindows()) {
// do tests...
}
}
This extra boiler plate code is not ideal.
Alternatively I have created a JUnit rule that only runs the test method on Windows:
public class WindowsOnlyRule implements TestRule {
#Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
if (isWindows()) {
base.evaluate();
}
}
};
}
private boolean isWindows() {
return System.getProperty("os.name").startsWith("Windows");
}
}
And this can be enforced by adding this annotated field to my test class:
#Rule public WindowsOnlyRule runTestOnlyOnWindows = new WindowsOnlyRule();
Both these mechanisms are deficient in my opinion in that on a Unix machine they will silently pass. It would be nicer if they could be marked somehow at execution time with something similar to #Ignore
Does anybody have an alternative suggestion?
In Junit5, There are options for configuring or run the test for specific Operating System.
#EnabledOnOs({ LINUX, MAC })
void onLinuxOrMac() {
}
#DisabledOnOs(WINDOWS)
void notOnWindows() {
// ...
}
Have you looked into assumptions? In the before method you can do this:
#Before
public void windowsOnly() {
org.junit.Assume.assumeTrue(isWindows());
}
Documentation: http://junit.sourceforge.net/javadoc/org/junit/Assume.html
Have you looked at JUnit assumptions ?
useful for stating assumptions about the conditions in which a test
is meaningful. A failed assumption does not mean the code is broken,
but that the test provides no useful information. The default JUnit
runner treats tests with failing assumptions as ignored
(which seems to meet your criteria for ignoring these tests).
If you use Apache Commons Lang's SystemUtils:
In your #Before method, or inside tests that you don't want to run on Win, you can add:
Assume.assumeTrue(SystemUtils.IS_OS_WINDOWS);
Presumably you do not need to actually call the Windows API as part of the junit test; you only care that the class which is the target of the unit test calls what it thinks is a the windows API.
Consider mocking the windows api calls as part of the unit tests.

Categories

Resources