I want to know if there is any technical difference between the following, when writing JUnit tests:
Option 1:
Define a setup method, i.e annotated with #Before, to initialize test fixture state before any #Test method is run.
Option 2:
Define a private method - just a plain old private method without any annotation - that does the same initialization, and make the first line of every #Test method a call to this method. (Ignore the possibility of someone forgetting to call the method in every test. I am looking for technical differences, not human factors)
Example of Option 2:
public class MyTest {
private void runSetupLogic() {
// whatever #Before method would have done
}
#Test
public void testMethod1() {
runSetupLogic();
// test logic
}
#Test
public void testMethod2() {
runSetupLogic();
// test logic
}
}
They are not really exactly the same, but for all intents and purposes either way should be fine. However, if you are interested in the technical analysis then my shaky understanding of the current JUnit 4 code on Github follows:
Here is what seems to be the actual code being ran when you use #Before using the default JUnit 4 runner src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java:
/**
* Returns a {#link Statement}: run all non-overridden {#code #Before}
* methods on this class and superclasses before running {#code next}; if
* any throws an Exception, stop execution and pass the exception on.
*/
protected Statement withBefores(FrameworkMethod method, Object target,
Statement statement) {
List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
Before.class);
return befores.isEmpty() ? statement : new RunBefores(statement,
befores, target);
}
The above calls RunBefores in src/main/java/org/junit/internal/runners/statements/RunBefores.java:
public class RunBefores extends Statement {
private final Statement next;
private final Object target;
private final List<FrameworkMethod> befores;
public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
this.next = next;
this.befores = befores;
this.target = target;
}
#Override
public void evaluate() throws Throwable {
for (FrameworkMethod before : befores) {
before.invokeExplosively(target);
}
next.evaluate();
}
The invokeExplosively method definition is in src/main/java/org/junit/runners/model/FrameworkMethod.java:
public Object invokeExplosively(final Object target, final Object... params)
throws Throwable {
return new ReflectiveCallable() {
#Override
protected Object runReflectiveCall() throws Throwable {
return method.invoke(target, params);
}
}.run();
}
which seems to use reflection to invoke the methods annotated with #Before.
Anyway, hope this answer is somewhat correct, but I'm not sure. If anyone has any corrections I can edit them in from the comments. By the way, for reference here is the javadoc for the #Before annotation: http://junit.org/javadoc/latest/org/junit/Before.html
I do not believe so.
However, if you were you implement another function, such as tearDown(), that would function essentially as an #After method, I would argue you might as well use them for readability, for the benefit of other collaborators or maybe even yourself.
The upside to using #Before and #After annotations is the that they avoid having to call a method at the beginning of each unit test, designed to save you the extra maintenance. If for some reason you had forgotten to add the call to your setUp() and/or tearDown() method, who knows what could go wrong.
This is, of course, if you need the EXACT SAME setup before each test. If you envision having a completely different setup for different unit tests, than perhaps you should look at the functionality of the class you are testing and ask yourself if perhaps you could modularize more.
The benifit comes from reporting.
In your method: runSetupLogic()
when ran from the start of a test, is reported within the test. Not as part of the setup and not as part of the initialization.
If the setup method fails, you get an accurate description of what failed... setup vs testing.
The before method allows you to isolate test failures from setup failures and allows the reporting solution to know as well.
Related
I tried looking for this over StackOverflow and even Google, but either I am using wrong keywords to find my answer or there is no direct answer yet.
My question is, is there a difference in performance or functionalities between using the setup() method and calling a method from within the test itself?
For example:
Tests with a setup method annotated with #Before annotation, which is called for each test run.
public class TestSetup extends TestCase {
private String name;
#Before
public void setup( ) {
this.name = "abc";
}
#Test
public void test1() { assertEquals("xyz", this.name); }
#Test
public void test2() { assertEquals("abc", this.name); }
}
Writing a test which calls a method before executing.
public class TestSetup extends TestCase {
private String name;
public void setName() {
this.name = "abc";
}
#Test
public void test1() {
setName();
assertEquals("xyz", this.name);
}
#Test
public void test2() {
setName();
assertEquals("abc", this.name);
}
}
What difference does this make except for the fact that in the latter case, the programmer needs to be aware that (s)he has to call the setup functions for the ones (s)he actually wants to use it.
Setup method is used for pre-conditions like object/resource initialization like mock object,softassertions object etc .Its upto developers whether to use the method or not .Junit/TestNg what ever framework you take all the common object s intialization/object creation will be done in setup i.e #Before annotation. Moreover you know that #Before will be called prior to the execution of test case.
Though for simple test method it wont't cause any impacts in your logic but for bulk classes with many test methods it may cause RunTimeException or even error related tomethod area in JVMor PermGen space if you keep on calling the same method stack.
To overcome this the same logic you can write in setup method once instead of calling same method multiple times unless you need different logic .
Hope you got the context of setup method.
Below mentioned is the class that I need to test:
public class MyClass {
private String key;
public MyClass(Connection con) {
key = ThirdPartyApi.getkey(con);
}
public String getKey() {
return key;
}
}
Now I need to test this constructor, but am unable to mock this Third party API call. And the Test case would be as mentioned below :
public class MyClassTest{
#Test
public void test1(){
MyClass c = new MyClass(dummyconnection);
assertNotNull(c.getKey != null);
}
}
But this case would be giving me an error that ThirdPartyAPI Class is failing as the the connection object is mocked.
So I want to mock this ThirdPartyApi call. Is it possible using Easymock, powermock?
Simple: EasyMock does not support mocking static calls. So you can turn to PowerMock(ito) or JMockit in case you do not want to change your code.
But the better approach would be to understand that using static always leads to tight coupling between your classes, and that you want to make sure that this doesn't affect your ability to unit test your code.
In your case:
public MyClass(Connection con) {
key = ThirdPartyApi.getkey(con);
simply replace that with:
public MyClass(Connection con) {
this (ThirdPartyApi.getkey(con));
}
/** unit testing only */
MyClass(Key key) {
...
And voila, you got a constructor that you can call from your unit test - and now you simply pass a mocked key object. And your tests will no longer execute that static call - because you use the key-taking constructor in all your tests.
But you probably want another test case to make sure that calling the public constructor does what you expect it to do - and that could be to throw an exception because that static call fails.
Beyond that: I fully agree with the comments - the fact that your constructor is doing so much (including static calls) has a certain design smell on it.
Let's say I have the following code:
protected int returnFourtyTwo() {
evilMethod(new Object, "");
return 42;
}
protected static void evilMethod(Object obj, String string) {
throw new RuntimeException("This is me being evil.");
}
What I'm trying to do is to run my returnFourtyTwo() method without throwing the runtime exception in my unit test. I've been able to use the suppress() method to bypass class constructors before just fine, but this is the first time I've had to bypass a static method (with more than one argument) in a non-static class. Unfortunately, resources on the topic are a bit scarce.
Your only way out is to mock the static method, as mentioned by #Dave. You can do that with PowerMock.
See Mocking static methods with Mockito.
Depending on how complicated your actual method implementation is, you could separate your return call from your exception throwing - then test on the return call which will not throw the exception. In a lot of cases it's best if strange ints such as 42 have their own variable anyway to explain what it corresponds too - If it is always 42, then it is static and final.
This is what I would do for your exact situation here, but I'm guessing this is a major simple abstraction from your actual problem so you probably still want to mock it as previously suggested.
static final int theAnswerToLife = 42;
protected int returnFourtyTwo() {
evilMethod(new Object, "");
return getTheAnswerToLife();
}
protected int getTheAnswerToLife() {
return theAnswerToLife;
}
protected static void evilMethod(Object obj, String string) {
throw new RuntimeException("This is me being evil.");
}
I don't say it is a good approach, but at least it works and it is not that bad.
you can do this :
create a public method in your inTest class and move your static method call there
in your unit test - you are testing inTest class - you can use a spy instead of mock for your inTest class
just ask unit test to do nothing for that method!
down side? we have a public method instead of private
Example :
I am unit testing the recyclerView Adapter :
I have a logger which has static method call so I moved all logs to a method
fun logMe(message: String) {
MyCrashAnalytics.leaveBreadcrumb(message)
}
and in unit test we have:
val underTest = MyAdapter(....)
then in tests or in setup method we can do this.
val spiedUnderTest = spy(underTest)
doNothing().`when`(spiedUnderTest).logMe(anyString())
Then we are good to go!
In simple you can use #Ignore annotation to your method.
Is it possible to control the value of the global variable in the class that I test?
The global variable is used in a private method, so I use a public method (in the same class) to pass through it.
How can I say that mListValService != null?
public class Myclass {
//my global variable
private ListValServiceRemote listValService = null;
public String getCodeValeurRef(Long idValeur) {
return getListValService().getRlvCode(idValeur);
// I want 100% coverage on this method so i have to change the value
// of mListValService.
private ListValServiceRemote getListValService() {
if (listValService == null) {
listValService = ServiceGetter.getListValService();
}
return listValService;
}
ReflectionTestUtils from spring-test might be a solution to access the field value. You can also use plain old reflection, add getter/setter to the field or make the field protected and put the test in the same package as the tested class.
Sample test:
public class MyclassTest {
private MyClass myClass;
#Before
public void setup() {
this.myClass = new MyClass();
}
#Test
public void testGetListValServiceWhenFieldIsNull() {
assertNotNull(this.myClass.getListValService());
}
#Test
public void testGetListValServiceWhenFieldIsNotNull() {
final ListValServiceRemote lvsr = new ListValServiceRemote();
ReflectionTestUtils.setField(this.myClass, "listValService", lvsr);
assertSame(lvsr, this.myClass.getListValService());
}
}
First of all, seems you are not using IoC technique, and hence you have problems while unit testing the code.
Secondly, a private is the private, don't test it. Your code should be tested and covered only by using public methods. If some code is not reachable via public interface, then it is not reachable at all. Why do you want to test it then?
This particular code could be easily 100% covered if you just invoke getCodeValeurRef() twice. And also if you would have listValService == null, it will cause NullPointerException failing the test anyway, so an assert is not required.
You could expose the getListValService() method as package-private, then call it in a test. You can confirm the same value is returned each time:
#Test
public void sameListValTest() {
Myclass foo = // construct this somewhow
assertTrue(foo.getListValService() == foo.getListValService());
}
This will give you 100% coverage without fiddling with a private field.
Or you could just call getCodeValeurRef() twice in your test to achieve the same results. Anything that causes the getListValService() to execute twice will give you 100% coverage. Exposing it as package-private allows you to verify that you are re-using the same field, not creating one each time (if that's important).
use case is simple: I want to run some boiler plate code before each method in JUnit test annotated with #Test and my custom annotation (let's call it #Mine).
I do not want to use following methods (explanation in parenthesis):
#RunWith (my test may, or may not use this annotation already, so I cannot assume that I will be able to use my own runner)
AOP (I cannot make any dependencies to third party libraries, such as AspectJ)
I guess this leaves me with reflection only, which is fine by me. I thought off using #Before accompanied with getting current method via Thread.getCurrentThread() etc. but somehow I find this solution to be a little bit dirty, since I would have to make boiler plate code again within this method to fire reflection (and avoiding any unnecessary code was the goal in the first place).
Maybe you have some other ideas?
You need a solution very similar to the answer to Mark unit test as an expected failure, based upon a TestRule. Using the example of a #Deprecated annotation (you can use yours here), you can insert code if the annotation exists on the method. The Description class contains the list of annotations on the method.
public class ExecutionTest {
public class BeforeExecution implements TestRule {
public Statement apply(Statement base, Description description) {
return statement(base, description);
}
private Statement statement(final Statement base, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
if (description.getAnnotation(Deprecated.class) != null) {
// you can do whatever you like here.
System.err.println("this will be run when the method has an #Deprecated annotation");
}
base.evaluate();
}
};
}
}
#Rule public BeforeExecution beforeExecution = new BeforeExecution();
// Will have code executed.
#Deprecated
#Test public void test1() {
// stuff
}
// won't have code executed.
#Test public void test2() {
// stuff
}
}
I would split the class into two. One with the methods you would have annotated with #mine and one for the others.
Then use #before as normal.
This adds no none standard code and will be easy to understand and maintain for future developers as well.