Manual bean autowiring doesn't work in JUnit test - java

My Junit test code looks like this.
private static boolean setupDone = false;
private Box box;
#Before
public void setup(){
if (setupDone){
return true;
}
box = new BoxCreator(this.applicationContext);
applicationContext.getAutowireCapableBeanFactory().autowireBean(box);
setupDone = true;
}
#Test
public void Test1(){
String response = box.getBoxResponse();
...asserts go here as usual....
}
#Test
public void Test2(){
String response = box.getBoxResponse();
...asserts go here as usual....
}
Now what happens is that Setup method runs only once as desired by virtue of setupDone variable.
Setup method after creating an instance of Box object autowires it as seen in the code above. Intention is to have a singleton of this class and use the same instance in every test.
Now the problem is that whichever test method runs first gets the value of box object and the second test method sees box as null. Not sure why it becomes null when the second test method is executed.

I suspect its not using the same instance of the test class for each test method's run.
If you make "box" static, it might work better. Note that "setupDone" and "box" are initialized in the #Before method together and should reside in the same place whether its the class as for statics or the instance as for merely global variables.
The problem with that is that if one test modifies the state of the object or its inner objects, a following test might not work right.

As Lee Meador mentioned, JUnit creates a new instance of the test class before invoking each #Test method. By doing this it provides independence between test methods and avoids unintentional side effects in the test code. Each test should be individually executed without any effect of the previous test and hence should have different application contexts in your case.

Related

JMockit: verify self method invocations of tested object

I have following class which I need to write unit tests to. I need to verify the invocations of own methods of MyClass by itself.
public class MyClass {
public void init() {
}
public void testMethod() {
}
}
I wrote following test class to test MyClass
public class MyClassTest {
#Tested
MyClass myClass;
#Test
public void initTest() {
// new Expectations(myClass) {{
// }};
myClass.init();
new Verifications() {{
myClass.testMethod();
}};
}
}
As it can be seen, init() does not call testMethod(), but for my surprise, above test case succeeds.
If I partially mock myClass by uncommenting the empty Expectations block above, test fails with Missing invocation error, which is expected. So, it seems that I have to partially mock the tested object.
But, partially mocking a test object of a complex class throws various exceptions when testing, which is very hard to debug because breakpoints in Intellij IDEA doesn't work in this situation.
So, what may be going wrong here? Or, is it not supposed to verify the invocations of methods in the tested object itself?
JMockit cannot verify method invocations on non-mocked class. In your example as stated, with the commented-out Expectations, the myClass object is not mocked at all, and verifications cannot actually verify that methods on it got called. It's not, strictly speaking, because you are verifying the #Tested object; you'd get the same issue if you created a new List and tried putting one of its methods in the Verifications.

How to make the unit test execute a particular test case everytime when it sees a certain function in the executing java project?

I am having a build failure issue while running a bunch of unit test over a java project. I am getting the NoClassDefFoundError which is happening because of the lack of ability for the unit test to get the dependencies. I am trying to mock an object for the class and then call the function, but the code is structured in a way that is getting a bit complex for me to handle the issue. I am very new to unit testing. I have provided below, a sample of code structure that my project has
Class ServiceProvider(){
obj declarations;
public void mainFunction(){
//Does a couple of things and calls a function in another class
boolean val = subFunction();
}
public boolean subFunction(){
boolean val = AnotherClass.someFunction(text);
//this function throws lots of exceptions and all those are caught and handled
return val;
}
#RunsWith(MockitoJUnitRunner.class)
Class UnitTestBunch(){
#Mock
AnotherClass acObj = new AnotherClass();
#InjectMock
ServiceProvider sp = new ServiceProvider();
#Test
public void unitTest1() throws Exception{
when(acObj.someFunction(text)).thenReturn(true);
}
#Test
public void unitTest2() throws Exception{
thrown.expect(ExceptionName.Class);
sp.mainFunction();
}
I have a test that uses the mock object and performs the function call associated with that class. But, the issue here is that there are a bunch of other unit test cases that are written similar to the unitTest2 function and calls the mainFunction at the end of the test. This mainFunction invokes someFunction() and causes NoCalssDefFoundError(). I am trying to make the unit test execute the content in unitTest1 everytime when it sees the AnotherClass.someFunction(). I am not sure if this is achievable or not. There could be another better way to resolve this issue. Could someone please pitch in some ideas?
In your test you seem to be using unitTest1 for setup, not for testing anything. When you run a unit test, each test should be able to run separately or together, in any order.
You're using JUnit4 in your tests, so it would be very easy to add the statement you have in unitTest1 into a #Before method. JUnit4 will call this method before each test method (annotated with #Test).
#Before
public void stubAcObj() throws Exception{
when(acObj.someFunction(text)).thenReturn(true);
}
The method may be named anything, though setUp() is a common name borrowed from a method to override in JUnit3. However, it must be annotated with org.junit.Before.
If you need this from multiple test cases, you should just create a helper, as you would with any code. This doesn't work as well with #InjectMocks, but you may want to avoid using #InjectMocks in general as it will fail silently if you add a dependency to your system-under-test.
public class AnotherClassTestHelper {
/** Returns a Mockito mock of AnotherClass with a stub for someFunction. */
public static AnotherClass createAnotherClassMock() {
AnotherClass mockAnotherClass = Mockito.mock(AnotherClass.class);
when(mockAnotherClass.someFunction(text)).thenReturn(true);
return mockAnotherClass;
}
}
As a side note, this is a counterintuitive pattern:
/* BAD */
#Mock
AnotherClass acObj = new AnotherClass();
You create a new, real AnotherClass, then instruct Mockito to overwrite it with a mock (in MockitoJUnitRunner). It's much better just to say:
/* GOOD */
#Mock AnotherClass acObj;

How to write unit test by mocking, when you have zero arg:constructors

I was trying to write unit test using jmocks and junit. (My Project uses core java- no frameworks-) I could not write unit test for some of my classes, by mocking external dependencies, when dependencies were initialized in a a no arg-constructor.
As i cannot provide the actual code, trying to explain the scenario by an example
public interface Apple {
String variety();
}
Implementation.
public class MalgovaApple implements Apple {
#Override
public String variety() {
return "Malgova";
}
}
Class to be tested
public class VarietyChecker {
private Apple apple;
VarietyChecker(){
this.apple = new MalgovaApple();
// instead of new, a factory method is used in actual application
}
public String printAppleVariety(){
String variety = apple.variety();
if(variety.length() < 3){
System.out.println("Donot use Code names- Use complete names");
return "bad";
}
return "good";
}
}
Junit test using jmock
public class VarietyCheckerUnitTest{
Mockery context = new JUnit4Mockery();
#Before
public void setUp() throws Exception {
}
#After
public void tearDown() throws Exception {
}
#Test
public void test_VarietyChecker() throws Exception{
final Apple mockapple = context.mock(Apple.class);
VarietyChecker printer = new VarietyChecker();
context.checking(new Expectations(){{
oneOf(mockapple).variety();will(returnValue("as"));
}});
String varietyNameValid = printer.printAppleVariety();
assertEquals("bad",varietyNameValid);
} }
This test fails - Mocking does not work the values "as" is not injected, the test class executes with MalgovaApple ...
Now if we add below constructor to VarietyChecker and use it test case - it gives expected output...
public VarietyChecker(Apple apple) {
super();
this.apple = apple;
}
and in unit test create test class object like
VarietyChecker printer = new VarietyChecker(mockapple);
Exposing a new constructor just for the purpose of testing is not a good idea. After all it is said that you should not alter the code for testing alone, more than that, i am afraid we have already written "some"(amount) code...
Am i missing something in junit or jmock that can make mocking work even incase of no-arg constructors. Or is this a limitation of simple junit and jmocks and should i migrate to something powerful like Jmockit /PowerMock
You should consider two choices.
Use a constructor parameter as you describe.
In this case, you're not "exposing a new constructor just for the purpose of testing". You're making your class more flexible by allowing callers to use a different factory implementation.
Don't mock it.
In this case, you are declaring that it never makes sense to use a different factory. Sometimes this is okay. At that point, the question changes, though. Instead of, "How do I mock this?" your question is now, "What am I gaining from writing this test?" You might not be gaining much of anything, and it might not make much sense to write the test at all.
If you don't mock it and decide a unit test is still worth it, then you should be asserting on other aspects of the code. Either an end state or some output. In this case, the factory call becomes an implementation detail that's not appropriate for mocking.
It's important not to fall for a "unit test everything" mentality. That is a recipe for Test-induced Design Damage. Evaluate your tests on a case by case basis, deciding whether they're providing you any real value or not. Not writing a unit test is a valid option and is even appropriate at times, even if it's option you try very hard to avoid.
Only you can make a determination which one makes the most sense in this case. From the the fact that this is a factory object we're talking about, I'd probably lean toward the former.

JUnit - fields that are one time initiated in #Before are null in tests

Like the title says I keep getting fields that are null down in the test cases even though I've initiated them in the #Before method as a one-time set-up. The only exception is that the first test that runs, works.
I was able to replicate the behaviour with the following code:
public class NetworkTest extends TestCase{
private static Boolean oneTimeSetUpDone = false;
private Client client;
#Before
public void setUp(){
if(!oneTimeSetUpDone){
client = new Client();
oneTimeSetUpDone = true;
}
}
#Test
public void testConnection(){
System.out.println(client);
assertFalse(true);
}
#Test
public void testMultiConnection(){
System.out.println(client);
assertFalse(true);
}
Am I missing something here or why would the fields get cleared after the first test is run?
#Before is run before each test - you should think of every #Test running in a new instance of the test class, and #Before sets up that instance (pro tip: look at the class' .hashCode() - it's different in each test method).
You can use #BeforeClass in your case.
Cheers,
Each test case in your test class, gets it's own copy of the instance variables. However your static field
private static Boolean oneTimeSetUpDone = false;
is shared among all the test cases. For each test case, the #Before method is execuded. What happens is that you're initializing the instance fields only for the first case - it's the if statement that sets the above flag to true, thus leaving the instance variables for other test cases uninitialized.
You have two options, depending on the instance fields. First answer this question, does it make sense to reuse the same instance field objects for each test case?
If it does, you could make them static, and your #Before method shall do fine as it is now.
Otherwise, you should remove the boolean flag, along with the if statement. That is, you need to initialize the instance variables for each test case, since they need to be "fresh" for each test case.
P.S. make your boolean field simply boolean instead of Boolean.

Junit test can't pass all test case once

I have a very strange problem, when i try to run a JUnit test with multiple test case, it will only pass the first test case and shown IndexOut of Bound error
public class ABCTest {
#Test
public void basicTest1(){...}
#Test
public void basicTest2(){...}
...
but if i commend the rest test case, test them one by one, it will pass all of them.
public class ABCTest {
#Test
public void basicTest1(){...}
//#Test
//public void basicTest2(){...}
//...
Since you do not provide the complete testcase and implementation class, I have to make some assumptions.
Most likely you are mutating the state of the tested object by the testcase.
Usually you try to get a clean test fixture for each unit test. This works by having a method with the #Before annotation which creates a new instance of the class under test. (This was called 'setUp()' in older versions of junit.)
This ensures that the order of test method execution as well as the number of executions does not matter and each method is working isolated.
Look at what you are doing inside of the test case and see if you are changing data that may be used by the other test cases and not restoring it to the original state. For example you have a text file that you read and write to in basicTest1 that you then read again in basicTest2 but assume the file is the same as it was before you ran basicTest1.
This is just one possible problem. would need to see the code for more insight

Categories