Common #before and #after for test classes in junit - java

Is it possible to have a common #Before and #After fixtures that can be used across multiple test classes?
I have segregated the tests (into classes) based on modules (Inventory, Sales, Purchase etc.). For all these tests, user Login is a prerequisite, currently I am having it in #Before for each class. The problem is when I need to change user id or password, I need to change in every class. Is there a way to write the #Before / #After that can be used in all the test classes? Does testsuite come handy by any means in this case?

The #Before and #After are applicable to inheritance:
public abstract class AbstractTestCase {
#Before
public void setUp() {
// do common stuff
}
}
If you want to do specific stuff in each test case you can override it:
public class ConcreteTestCase extends AbstractTestCase {
#Before
#Override
public void setUp() {
super.setUp();
// do specific stuff
}
}

You can create a #ClassRule for your test suite. It is invoked for each test. See API and Example for ExternalResource on how to apply before/after.

you can use #Before annotations in an abstract parent class like so:
public class TestMe extends TestParent {
#Test
public void test() {
System.out.println("Hi, here is a test. The username is: " + getUsername());
}
}
with parent class:
public abstract class TestParent {
private String username;
#Before
public void setUp() {
username = "fred";
}
public String getUsername() {
return username;
}
}

I know 2 solutions:
Use abstract base class as it is mentioned in comment by #vikingsteve.
Use Rules. You can implement your custom rule that does what you need and then add it to each test case you need.
public class MyTest {
#Rule Rule myBeforeAfterRule = new MyTestLifecycleRule();
// your code
}
The rule-based solution IMHO is more flexible because inheritance is not always applicable for all use-cases. Moreover you can combine several rules in one test case.

Related

How to write non-encapsulated unit tests?

I have an autowired variable
#Autowired
private DocumentConfig documentConfig;
I want to make tests for the DocumentService with various states of this configuration object. What are my options? What is the best option?
The first idea is this:
#Test
public void save_failure() {
documentConfig.setNameRequired(true);
/*
testing code goes here
*/
documentConfig.setNameRequired(false);
}
But I want to be somewhat more sure that the variable is reset after the test to not interfere with the other tests, to make sure only this test gets an error if it's the source of a problem.
My new idea was this:
#Before
public void after() { documentConfig.setNameRequired(true); }
#Test
public void save_failure() {
/*
testing code goes here
*/
}
#After
public void after() { documentConfig.setNameRequired(false); }
However, this doesn't work at all because Before and After execute for the whole file and not this single test. I would prefer not to make a new file just for one test.
I've now settled on a compromise:
#Test
public void save_failure() {
documentConfig.setNameRequired(true);
/*
testing code goes here
*/
}
#After
public void after() { documentConfig.setNameRequired(false); }
It seems to do everything I want but I have a few questions.
Assuming nameRequired starts as false, is this guaranteed not to interfere with the other tests?
Is there any way I can make this more clear? Both for my future self and for others.
You can create it before each test. Smth like
private DocumentConfig documentConfig;
#Before
public void createConfig() {
documentConfig = new DocumentConfig(mockedParams);
}
An often used approach is to set up a dummy DocumentConfig and inject it within the setUp() method (annotated with #Before) so that the entire context is reset within each test, for example:
#Before
public void setUp() {
this.documentConfig = new DocumentConfig();
this.documentConfig.setNameRequired(false);
this.service = new DocumentService(this.documentConfig);
}
In this case, I've set up a simple object with nameRequired being false. I could probably delete that statement, because a boolean field defaults to false anyways.
If you don't use constructor injection, and you don't have a setter for documentConfig, you'll have to use reflection to inject the field, for example:
ReflectionTestUtils.setField(this.service, "documentConfig", this.documentConfig);
Within your test you could now write something like this:
#Test
public void save_failure() {
this.documentConfig.setNameRequired(true);
// TODO: Implement test
}
Alternatively, you could mock DocumentConfig, so that you don't rely on its implementation to test DocumentService. I assume that you're calling isNameRequired() somewhere in the code of DocumentService, so you could mock it like this:
#Before
public void setUp() {
// Use a static import for Mockito.mock()
this.documentConfig = mock(DocumentConfig.class);
this.service = new DocumentService(this.documentConfig);
}
#Test
public void save_failure() {
// Use a static import for Mockito.when()
when(this.documentConfig.isNameRequired()).thenReturn(true);
// TODO: Implement test
}
Since this mocking/injection setup happens quite often, Mockito also has its own runner that allows you to get rid of the setUp() method, for example:
#RunWith(MockitoJUnitRunner.class)
public class DocumentServiceTest {
#InjectMocks
private DocumentService documentService;
#Mock
private DocumentConfig documentConfig;
#Test
public void save_failure() {
when(this.documentConfig.isNameRequired()).thenReturn(true);
// TODO: Implement test
}
}
It is not yet clear, which testing framework you use. For plain unit tests, make the value injectable by either a setter or constructor injection. Whatever suits your specific situation best.
If there's a lot (more than three ;-) ) of such values to be injected, you may consider introducing a configuration class to inject all those values as a single parameter.

JUnit Contract Testing with Suites

I have an interface that defines a contract (i.e. a Repository), with few implementations. Each method in the interface represents a feature, and I would like to test each feature in its suite test class.
Let's assume a UserRepository interface as follows:
public interface UserRepository {
Set<User> search(String query);
Set<User> findBySomethingSpecific(String criteria1, Integer criteria2);
}
At the moment, to ensure I run the same test cases, I create an abstract test class, and each of my implementations have a test class that extends the abstract test class.
public abstract UserRepositoryTest {
private UserRepository userRepository;
#Before
public void setUp() {
userRepository = createUserRepository();
}
#Test public void aTestForSearch() { ... }
#Test public void anotherTestForSearch() { ... }
#Test public void aTestForSomethingSpecific() { ... }
#Test public void anotherTestForSomethingSpecific() { ... }
protected abstract UserRepository createUserRepository();
}
//------------------------
public class UserRepositoryImplementationTest extends UserRepositoryTest {
#Override
protected UserRepository createUserRepository() {
return new UserRepositoryImplementation();
}
}
I would like to find a way to divide this abstract test class into a set of small tests, because the test class becomes rapidly overwhelmed. I've looked at test suites, but I don't understand how can I create a Suite test class by injecting my different implementations.
As a side not, I've found this question, but some of my repositories require some logic at its creation (for instance, ConnectionPool for a SQL implementation). I currently use the anti-pattern ServiceLocator with different Context classes to handle the creation, but this is static. That's why I had an approach of a test class by implementation, so I can create the context and inject it afterward.
Whit Junit 4 you can create a suite like this:
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
#RunWith(Suite.class)
#Suite.SuiteClasses({
TestFeatureLogin.class,
TestFeatureLogout.class,
TestFeatureNavigate.class,
TestFeatureUpdate.class
})
/**
*
* This suite will execute TestFeatureLogin,TestFeatureLogout,TestFeatureNavigate and TestFeatureUpdate one after the over.
*
* #Before, #After and #Test are no possible of executing in this class.
* #BeforeClas and #AfterClass are allowed only.
*
* */
public class FeatureTestSuite {
// the class remains empty of test,although it is possible set up a before class and after class annotations.
// used only as a holder for the above annotations
#BeforeClass
static public void beforeClass(){
System.out.println(FeatureTestSuite.class.toString() + " BeforeClass Method");
}
#AfterClass
static public void AfterClass(){
System.out.println(FeatureTestSuite.class.toString() + " AfterClass Method");
}
}
The complete example could be found here
Another thing you have to have into account is that #Test is no a good practice of unit testing inside Abstract class. If you want to test your implementations create test classes that extend of Abstract class.

Best practice - Setting a field without setters in a unit test

Let's say you have the following class you would like to test:
public class SomeService {
public String someMethod(SomeEntity someEntity) {
return someEntity.getSomeProperty();
}
}
The SomeEntity looks like this:
public class SomeEntity {
private String someProperty;
public getSomeProperty() {
return this.someProperty;
}
}
The assertion you would like to do can be the following:
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
How can you make this test work?
1) Add a setter for 'someProperty' in the SomeEntity class. I don't think this a good solution because you don't change production code to make your tests work.
2) Use ReflectionUtils to set the value of this field. Test would look like this:
public class TestClass {
private SomeService someService;
#Test
public void testSomeProperty() {
SomeEntity someEntity = new SomeEntity();
ReflectionTestUtils.setField(someEntity, "someProperty", "someValue");
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
}
}
3) You create an inner class in your test class that extends the SomeEntity class and adds the setter for this field. However, for this to work you will also need to change the SomeEntity class because the field should become 'protected' instead of 'private'. Test class might look like this:
public class TestClass {
private SomeService someService;
#Test
public void testSomeProperty() {
SomeEntityWithSetters someEntity = new SomeEntityTestWithSetters();
someEntity.setSomeProperty("someValue");
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
}
public class SomeEntityWithSetters extends SomeEntity {
public setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
}
}
4) You use Mockito to mock SomeEntity. Seems fine if you only need to mock only one property in the class, but what if you need to mock like 10 properties are so. The test might look like this:
public class TestClass {
private SomeService someService;
#Test
public void testSomeProperty() {
SomeEntity someEntity = mock(SomeEntity.class);
when(someEntity.getSomeProperty()).thenReturn("someValue");
String result = someService.someMethod(someEntity);
assertThat(result).isEqualTo("someValue");
}
}
you can set the value using reflection. It doesn't need any change in production code.
ReflectionTestUtils.setField(YourClass.class, "fieldName", fieldValue);
You can add a setter with default (package private) scope.
With junit testing of SomeService.someMethod()
alternative 1. should not use this as no need to change entity for writing junit.
alternative 2. can be used.
alternative 3. again same a 3, no need to extend for just junit. how about when the class cannot be extended.
alternative 4. yes, a good option. mockito is being used for the same reason.
What is the behavior / contract specific to SomeService that is testable? Based upon your skeletal code, there really isn't any. It will either throw a NPE on bad input, or return a String that may or may not be null, depending on Hibernate magic. Not sure what you can actually test.
I have been through this same dilemma many times before, a quick solution is to make the field you want to mock package protected, or provide a protected setter. Of course both will alter production code.
Alternatively, you can consider dependency injection framework, such as Dagger. Below is an example they give:
#Module
class DripCoffeeModule {
#Provides Heater provideHeater(Executor executor) {
return new CpuHeater(executor);
}
}
This JUnit test overrides DripCoffeeModule's binding for Heater with a mock object from Mockito. The mock gets injected into the CoffeeMaker and also into the test.
public class CoffeeMakerTest {
#Inject CoffeeMaker coffeeMaker;
#Inject Heater heater;
#Before public void setUp() {
ObjectGraph.create(new TestModule()).inject(this);
}
#Module(
includes = DripCoffeeModule.class,
injects = CoffeeMakerTest.class,
overrides = true
)
static class TestModule {
#Provides #Singleton Heater provideHeater() {
return Mockito.mock(Heater.class);
}
}
#Test public void testHeaterIsTurnedOnAndThenOff() {
Mockito.when(heater.isHot()).thenReturn(true);
coffeeMaker.brew();
Mockito.verify(heater, Mockito.times(1)).on();
Mockito.verify(heater, Mockito.times(1)).off();
}
}

Junit - run set up method once

I set up a class with a couple of tests and rather than using #Before I would like to have a setup method that executes only once before all tests. Is that possible with Junit 4.8?
Although I agree with #assylias that using #BeforeClass is a classic solution it is not always convenient. The method annotated with #BeforeClass must be static. It is very inconvenient for some tests that need instance of test case. For example Spring based tests that use #Autowired to work with services defined in spring context.
In this case I personally use regular setUp() method annotated with #Before annotation and manage my custom static(!) boolean flag:
private static boolean setUpIsDone = false;
.....
#Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
You can use the BeforeClass annotation:
#BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
JUnit 5 now has a #BeforeAll annotation:
Denotes that the annotated method should be executed before all #Test
methods in the current class or class hierarchy; analogous to JUnit
4’s #BeforeClass. Such methods must be static.
The lifecycle annotations of JUnit 5 seem to have finally gotten it right! You can guess which annotations available without even looking (e.g. #BeforeEach #AfterAll)
When setUp() is in a superclass of the test class (e.g. AbstractTestBase below), the accepted answer can be modified as follows:
public abstract class AbstractTestBase {
private static Class<? extends AbstractTestBase> testClass;
.....
public void setUp() {
if (this.getClass().equals(testClass)) {
return;
}
// do the setup - once per concrete test class
.....
testClass = this.getClass();
}
}
This should work for a single non-static setUp() method but I'm unable to produce an equivalent for tearDown() without straying into a world of complex reflection... Bounty points to anyone who can!
JUnit 5 #BeforeAll can be non static provided the lifecycle of the test class is per class, i.e., annotate the test class with a #TestInstance(Lifecycle.PER_CLASS) and you are good to go
Edit:
I just found out while debugging that the class is instantiated before every test too.
I guess the #BeforeClass annotation is the best here.
You can set up on the constructor too, the test class is a class after all.
I'm not sure if it's a bad practice because almost all other methods are annotated, but it works. You could create a constructor like that:
public UT () {
// initialize once here
}
#Test
// Some test here...
The ctor will be called before the tests because they are not static.
Use Spring's #PostConstruct method to do all initialization work and this method runs before any of the #Test is executed
Try this solution:
https://stackoverflow.com/a/46274919/907576 :
with #BeforeAllMethods/#AfterAllMethods annotation you could execute any method in Test class in an instance context, where all injected values are available.
My dirty solution is:
public class TestCaseExtended extends TestCase {
private boolean isInitialized = false;
private int serId;
#Override
public void setUp() throws Exception {
super.setUp();
if(!isInitialized) {
loadSaveNewSerId();
emptyTestResultsDirectory();
isInitialized = true;
}
}
...
}
I use it as a base base to all my testCases.
If you don't want to force a declaration of a variable that is set and checked on each subtest, then adding this to a SuperTest could do:
public abstract class SuperTest {
private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
protected final boolean initialized() {
final boolean[] absent = {false};
INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
return absent[0] = true;
});
return !absent[0];
}
}
public class SubTest extends SuperTest {
#Before
public void before() {
if ( super.initialized() ) return;
... magic ...
}
}
I solved this problem like this:
Add to your Base abstract class (I mean abstract class where you initialize your driver in setUpDriver() method) this part of code:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
And now, if your test classes will extends from Base abstract class -> setUpDriver() method will be executed before first #Test only ONE time per run.
Here is one alternative suggestion:
What I do to get this working is
Create a method named _warmup or just _
Annotate the test class with #FixMethodOrder(MethodSorters.NAME_ASCENDING)
This is applicable only if you run all tests in the class
It has a downside of having additional test included, which will also run one additional #Before and #After
It is usually advised for your test methods to be order independent, this breaks that rule, but why someone would like tests ordered randomly in the reports I have no clue so NAME_ASCENDING is what I always use
But the upsides to this is simple setup with minimal code and without the need to extend classes/runners etc...
Test run lengths are more accurate since all setup time is reported on method _warmup
After experimenting for some time this is my solution. I needed this for spring boot test. I tried using #PostConstruct, unfortunately it is executed for every test.
public class TestClass {
private static TestClass testClass = null;
#Before
public void setUp() {
if (testClass == null) {
// set up once
...
testClass = this;
}
}
#AfterClass
public static void cleanUpAfterAll() {
testClass.cleanUpAfterAllTests();
}
private void cleanUpAfterAllTests() {
// final cleanup after all tests
...
}
#Test
public void test1() {
// test 1
...
}
#Test
public void test2() {
// test 2
...
}
}
The problem with #BeforeClass is that it fires before the constructor.
So if you rely on an #Autowired constructor to provide data, it simply will not work: wrong execution order.
Similarly #PostConstruct fires after the constructor has been called. And the constructor fires with every #Test, therefore your setup function will fire with every test, if you use this.
This has the exact same effect as calling a function from the constructor.
The only solution, I found that works, is to use a flag to indicate if the setUp() method has already been executed. While its not ideal, it will drastically reduce the amount of processing before each test.
private static boolean initialized = false;
#Autowired
public CacheTest( MyBean myBean ){
this.myBean = myBean;
}
#PostConstruct
public static void setUp(){
if( initialized ) { return };
initialized = true;
//do suff with myBean
}

What order are the Junit #Before/#After called?

I have an Integration Test Suite. I have a IntegrationTestBase class for all my tests to extend. This base class has a #Before (public void setUp()) and #After (public void tearDown()) method to establish API and DB connections. What I've been doing is just overriding those two methods in each testcase and calling super.setUp() and super.tearDown(). However this can cause problems if someone forgets to call the super or puts them at the wrong place and an exception is thrown and they forget to call super in the finally or something.
What I want to do is make the setUp and tearDown methods on the base class final and then just add our own annotated #Before and #After methods. Doing some initial tests it appears to always call in this order:
Base #Before
Test #Before
Test
Test #After
Base #After
but I'm just a little concerned that the order isn't guaranteed and that it could cause problems. I looked around and haven't seen anything on the subject. Does anyone know if I can do that and not have any problems?
Code:
public class IntegrationTestBase {
#Before
public final void setUp() { *always called 1st?* }
#After
public final void tearDown() { *always called last?* }
}
public class MyTest extends IntegrationTestBase {
#Before
public final void before() { *always called 2nd?* }
#Test
public void test() { *always called 3rd?* }
#After
public final void after() { *always called 4th?* }
}
Yes, this behaviour is guaranteed:
#Before:
The #Before methods of superclasses will be run before those of the current class, unless they are overridden in the current class. No other ordering is defined.
#After:
The #After methods declared in superclasses will be run after those of the current class, unless they are overridden in the current class.
One potential gotcha that has bitten me before:
I like to have at most one #Before method in each test class, because order of running the #Before methods defined within a class is not guaranteed. Typically, I will call such a method setUpTest().
But, although #Before is documented as The #Before methods of superclasses will be run before those of the current class. No other ordering is defined., this only applies if each method marked with #Before has a unique name in the class hierarchy.
For example, I had the following:
public class AbstractFooTest {
#Before
public void setUpTest() {
...
}
}
public void FooTest extends AbstractFooTest {
#Before
public void setUpTest() {
...
}
}
I expected AbstractFooTest.setUpTest() to run before FooTest.setUpTest(), but only FooTest.setupTest() was executed. AbstractFooTest.setUpTest() was not called at all.
The code must be modified as follows to work:
public void FooTest extends AbstractFooTest {
#Before
public void setUpTest() {
super.setUpTest();
...
}
}
I think based on the documentation of the #Before and #After the right conclusion is to give the methods unique names. I use the following pattern in my tests:
public abstract class AbstractBaseTest {
#Before
public final void baseSetUp() { // or any other meaningful name
System.out.println("AbstractBaseTest.setUp");
}
#After
public final void baseTearDown() { // or any other meaningful name
System.out.println("AbstractBaseTest.tearDown");
}
}
and
public class Test extends AbstractBaseTest {
#Before
public void setUp() {
System.out.println("Test.setUp");
}
#After
public void tearDown() {
System.out.println("Test.tearDown");
}
#Test
public void test1() throws Exception {
System.out.println("test1");
}
#Test
public void test2() throws Exception {
System.out.println("test2");
}
}
give as a result
AbstractBaseTest.setUp
Test.setUp
test1
Test.tearDown
AbstractBaseTest.tearDown
AbstractBaseTest.setUp
Test.setUp
test2
Test.tearDown
AbstractBaseTest.tearDown
Advantage of this approach: Users of the AbstractBaseTest class cannot override the setUp/tearDown methods by accident. If they want to, they need to know the exact name and can do it.
(Minor) disadvantage of this approach: Users cannot see that there are things happening before or after their setUp/tearDown. They need to know that these things are provided by the abstract class. But I assume that's the reason why they use the abstract class
If you turn things around, you can declare your base class abstract, and have descendants declare setUp and tearDown methods (without annotations) that are called in the base class' annotated setUp and tearDown methods.
You can use #BeforeClass annotation to assure that setup() is always called first. Similarly, you can use #AfterClass annotation to assure that tearDown() is always called last.
This is usually not recommended, but it is supported.
It's not exactly what you want - but it'll essentially keep your DB connection open the entire time your tests are running, and then close it once and for all at the end.
This isn't an answer to the tagline question, but it is an answer to the problems mentioned in the body of the question. Instead of using #Before or #After, look into using #org.junit.Rule because it gives you more flexibility. ExternalResource (as of 4.7) is the rule you will be most interested in if you are managing connections. Also, If you want guaranteed execution order of your rules use a RuleChain (as of 4.10). I believe all of these were available when this question was asked. Code example below is copied from ExternalResource's javadocs.
public static class UsesExternalResource {
Server myServer= new Server();
#Rule
public ExternalResource resource= new ExternalResource() {
#Override
protected void before() throws Throwable {
myServer.connect();
};
#Override
protected void after() {
myServer.disconnect();
};
};
#Test
public void testFoo() {
new Client().run(myServer);
}
}

Categories