Do we still need JUnit's Before annotation? [duplicate] - java

This question already has answers here:
JUnit: using constructor instead of #Before
(8 answers)
Closed 5 years ago.
Using Junit 4.12. JUnit's Before annotation is documented, but it seems to me that it is no longer needed. Apparently JUnit creates a new instance for every test, as shown in the following snippet:
import org.junit.Test;
public class BeforeTest {
TestObject testObject = new TestObject();
#Test
public void one(){
System.out.println(testObject.status);
testObject.setStatus("Used by one()");
}
#Test
public void two(){
System.out.println(testObject.status);
testObject.setStatus("Used by two()");
}
private class TestObject{
public String status;
public TestObject(){
status = "new";
}
void setStatus(String newStatus){status = newStatus;}
}
}
-----------------------------
new
new
Do we still need #Before?

As in this similar question, methods annotated with #Before can usually be replaced with constructors / field initialization.
Some subtle differences exist that may make a difference in corner cases:
Exception Handling: Exceptions in #Before cause #After to be called, exceptions in constructor do not
Subclass initialization: #Before is called after the constructor has completed, allowing to access anything produced by child-class constructors
Subclassing: With #Before you can override parent class #Before methods, with constructors you always need to call one of the parent class constructors.
#Rule: The constructor is called before #Rule methods, #Before is called after #Rule methods

Related

Mocking dependencies in java object constructor [duplicate]

This question already has answers here:
How to mock constructor with PowerMockito
(1 answer)
Mock a constructor with parameter
(7 answers)
Closed 2 years ago.
I have a class that's composed of other objects/dependencies as follows:
public class One{
private RedisPool redisPool;
private static final WeakHashMap<String, Dedup<String>> CACHE = new WeakHashMap<>();
private static final ObjectMapper mapper = new ObjectMapper();
private BigQueryManager bigQueryManager;
private RedisClientManager redisClientManager;
private PubSubIntegration pubSub;
public One(RedisPool redisPool, Configuration config) {
this.redisPool = redisPool;
bigQueryManager = new BigQueryManager(config);
redisClientManager = new RedisClientManager(redisPool, config);
pubSub = new PubSubIntegration(config);
}
....
...
other methods
}
I tried:
public class OneTest{
#Mock
RedisPool redisPool;
#Mock
Configuration config;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
One one = new One(redisPool, config);
}
}
But I'm not sure whether the objects constructed inside the constructor also get mocked, as I have used those objects in other methods inside the class.
How can I mock the objects constructed inside the constructor?
I don't think you can achieve this using Mockito alone, but you can if you also use PowerMockito.
This article gives an example that is quite similar to what you want to achieve.
Note that PowerMockitio will mess up any test coverage statistics that you are collecting.
EDIT
If the article disappears, the gist of it is that you need to annotate your Test class slightly differently
#RunWith(PowerMockRunner.class)
#PrepareForTest(One.class)
public class OneTest {
The #PrepareForTest annotation refers to the Class that you need to alter the bahaviour of - in your case the One class.
You then tell PowerMoncito to return an object you can control when a new instance is created. In your case
PowerMockito.whenNew(BigQueryManager.class)
.withAnyArguments().thenReturn(mockBigQueryManager);

How to test a constructor will throw an illegal state exception? [duplicate]

This question already has answers here:
How can I access a private constructor of a class?
(21 answers)
Closed 3 years ago.
I have a utility class with a private constructor that throws an Illegal state exception and I want to test that it does this.
I've tried a test where I implement the constructor, but since the constructor is private it can't be accessed outside of the class. So is it just pointless to test the constructor?
from the class
private UtilityClass(){
throw new IllegalStateException("Utility Class");
}
from the test class
private UtilityClass = utilityClass;
#Test(expected = IllegalStateException.class)
public void constructorTest(){
utilityClass = new UtilityClass();
}
You can test that a constructor throws an exception by defining a public constructor and then writing appropriate test code. If you have a private constructor (or private method), you cannot directly test it.

Difference between using junit setup() method and calling a method from the tests itself

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.

Is it possible to Declare but not Instatiate a Spied Object in Mockito using #Spy Notation?

I am writing some JUnit tests for legacy code and I am a big fan of using annotations. I would like to know if it is possible to create a declaration to a spied object and later instantiate it. The reason I ask is because I have a class with a non-null constructor. The values for this constructor are not known until after setup of the test cases. The code below shows what I would like to do:
#RunWith(MockitoJUnitRunner.class)
public class ObjectUndertestTest {
#Spy private SomeClassToSpy someClassToSpy;
private Integer parameterOne;
private Integer parameterTwo;
#Before
public void setupTest() {
parameterOne = 1;
parameterTwo = 2;
someClassToSpy = new SomeClassToSpy(parameterOne, parameterTwo);
}
}
The only way that I can see to be able to do this is to mix my syntax and use the traditional spy(object to mock) notation. That is:
#RunWith(MockitoJUnitRunner.class)
public class ObjectUndertestTest {
private SomeClassToSpy someClassToSpy;
private Integer parameterOne;
private Integer parameterTwo;
#Before
public void setupTest() {
parameterOne = 1;
parameterTwo = 2;
someClassToSpy = new SomeClassToSpy(parameterOne, parameterTwo);
SomeClassToSpy spySomeClassToSpy spy(someClassToSpy);
}
}
Or something similar. Any thoughts on this?
Beware that #Spy isn't really a documentation annotation: It is an instruction for MockitoJUnitRunner (et al) to initialize the spy automatically for you according to its documented usage patterns. Though annotations are useful and informative, I think it may cause more confusion to use the annotation for its name and not its semantics.
That said, if it's just a matter of constructing an instance with your chosen constructor arguments, you can call the constructor directly and explicitly and use Mockito's initialization to wrap it in a spy (as in the #Spy docs):
#Spy private SomeClassToSpy someClassToSpy = new SomeClassToSpy(1, 2);
Though you'd be right to favor #Before methods over class initializers or constructors, this is an explicitly-documented method of initialization and one unlikely to cause test pollution or initialization-order problems.

Test if another method was called

So I'm sure there is something like this out there but I have been searching for an hour and haven't found exactly what I am looking for. say I have a class that looks like this:
public class MyClass
{
public void myMethod(boolean shouldCallOtherMethod)
{
if(shouldCallOtherMethod)
{
otherMethod();
}
}
public void otherMethod()
{
System.out.println("Called");
}
}
How do I make something like this work?
#Test
public void shouldCallMethod()
{
MyClass myClass = new MyClass();
myClass.myMethod(true)
// verify myClass.otherMethod method was called
}
Using Mockito, you can do spying on real objects like this:
import org.junit.Test;
import static org.mockito.Mockito.*;
public class MyClassTest {
#Test
public void otherMethodShouldBeCalled() {
MyClass myClass = new MyClass();
MyClass spy = spy(myClass);
spy.myMethod(true);
verify(spy).otherMethod();
}
}
There are some gotchas, so take a look at the relevant documentation as well.
Suppose MokeysClass has a constructor declared like this, where Foo is some other class.
public MokeysClass(String name, int counter, Foo myFoo)
I would write my test like this.
#RunWith(MockitoJUnitRunner.class)
public class TestArray {
#Mock
private Foo mockMyFoo;
private String nameToInject = "Mokey";
private int counterToInject = 42;
#Spy
private MokeysClass toTest = new MokeysClass(nameToInject, counterToInject, mockMyFoo);
#Test
public void shouldCallMethod() {
toTest.myMethod(true);
verify(toTest).otherMethod();
}
}
so that I am explicitly stating which constructor to call when I create my test object, and what arguments to pass to it.
There are some reasons not to rely on #InjectMocks to do this step for me, particularly if the class being tested is more complex and has more than one constructor. Mockito chooses the constructor that has the most arguments, but if there are several constructors with the same number of arguments, Mockito could choose any of the constructors; that is, the behaviour is undefined.
Once Mockito has chosen a constructor, it checks whether that constructor can in fact be used for constructor injection. Constructor injection will not be used if
one or more of the parameters of the chosen constructor is a primitive type,
the type of one or more of the parameters of the chosen constructor is a final class,
the type of one or more of the parameters of the chosen constructor is a private class,
the only constructor of the class is the default constructor.
If any one of these conditions holds, for the constructor that Mockito chose, then constructor injection won’t be used. In this case, the class must have a default constructor, otherwise Mockito will throw an exception.
The complexity of the criteria which Mockito uses when choosing whether to apply constructor injection implies that adding or removing a constructor, or changing the parameters of a constructor, can make Mockito switch from using constructor injection to using setter and field injection; or from using setter and field injection to using constructor injection. This can occur even if the constructor that is changed is not the one that will be used for constructor injection.
As a result, any test that uses constructor injection is automatically quite brittle; in the sense that changes that are not directly related to the test itself can cause the test to fail. Such failures can be difficult to troubleshoot.
The #InjectMocks annotation was designed for use with frameworks such as Spring that do dependency injection; and for tests of classes that use Spring, it can be invaluable. But if dependency injection is not part of your class, I would strongly recommend avoiding #InjectMocks on account of its brittleness. You really want your test code to be as easy to maintain and to troubleshoot as your production code is.
This is not recommended, but you can spy real object :)
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.BDDMockito.verify;
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Spy
private MyClass sut; // System Under Test
#Test
public void shouldCallMethod() {
// when
sut.myMethod(true);
// then
verify(sut).otherMethod();
}
}
Result:
Tests Passed: 1 passed in 0,203 s
After changing code: sut.myMethod(false);
Wanted but not invoked:
sut.otherMethod();
-> at my.custom.MyClassTest.shouldCallMethod(MyClassTest.java:23)
Source: Spying on real objects
Magic version with constructor injection
#Mock
private LexAnalyzer lexAnalyzer;
#Spy
#InjectMocks
private SyntaxAnalyzer sut; // System Under Test
#Test
public void shouldCallMethod() {
// when
sut.myMethod(true);
// then
verify(sut).otherMethod();
}
SyntaxAnalyzer.java
public class SyntaxAnalyzer {
private final LexAnalyzer lexAnalyzer;
public SyntaxAnalyzer(LexAnalyzer lexAnalyzer) {
this.lexAnalyzer = lexAnalyzer;
}
...
Tested, works ;)
I think you want to look at Mock objects. You can create a mock of MyClass, then set expectations that otherMethod() is called when you call myMethod and fails if it was not called.
Here is a pretty good overview of them for java - http://www.scalatest.org/user_guide/testing_with_mock_objects
One other major benefit of using Mocks, you can avoid side affects, like logging to NSLog or hitting a web server or printing) in your test.

Categories