How does Junit test work in the background? - java

I just started with Junit Testing very recently, so please excuse me if my terminology is not correct. As far as I know, the methods become a test method if we annotate it with a #test and we can run it with an IDE(I am using Intellij) by clicking on the play button next to it. In the background, it probably instantiates an instance of the Test class and run the selected method. My question is, in the example below, if test1 and test2 both use and edit the same hello string of the same instance of the Test class, since test2 runs after test1, it should print the edited version of the hello String? i.e: test2 should print "1". But in this case it prints an empty String. Why is this ?
class Test{
private String hello = "";
#Test
void test1() {
hello = hello + "1";
System.out.println(hello);
}
#Test
void test2() {
System.out.println(hello)
}
}

This happens due to the lifecycle of the test.
You've guessed correctly, indeed JUnit instantiates the Class of the test (class Test in this case).
In other words somewhere in the code of JUnit there is a line:
Test test = new Test() (in the real code it uses reflection, but it doesn't matter for the sake of the question).
Then it runs the test methods, so far so good - you were right:
Test test = new Test();
test.test1();
test.test2();
// handle failures, exceptions, etc.
However, JUnit is designed in a way that it instantiates the class of test before running every single test method. This is a design decision of the JUnit framework.
So, the "more accurate" representation of what happens in JUnit looks like this:
Test test = new Test();
test.test1();
....
test = new Test();
test.test2();
This is a default behavior of JUnit, all the data fields get instantiated over and over again for each test and it guarantees that test1 prints 1
and test2 prints an empty string.
This happens regardless the order of actual tests execution.
Now, this behavior can be altered by using #TestInstance(LifeCycle.PER_CLASS) annotation on the test class, but its a pretty advanced stuff. It will instruct the JUnit engine to create only one single object of class Test and run all the test methods in it. So if one test method will change the data field defined in the class Test the other test will actually see this change.
If you're interested to learn more about #TestInstance - consider reading this article for example

In most case Unit tests should not depend on the order or execution.
By default JUnit won't guaranty you an order of execution, in this case test1 could be executed after or before test2.
For tests you can use #BeforeEach or #BeforeAll to execute some code before your tests.
Also you can use #Order(1) to run force the test order. However I would strongly advocate again it except in really specific case.

Related

Mockito Mocking a return value and verify it

I have this class and wants to create a mock to return and verify the return value "50":
QAService.java:
#Path("/QAService")
public class QAService {
#GET()
//#Path("/")
#Produces("text/plain")
public String getServiceInfo() {
return "50";
}
My understanding of mock by defintion is that I can create a fake object of an implementation class and mock functions yet to be developed so I can test the interface.
Still I am creating this test to test mocking without having an interface. How do I verify it?:
QAServiceTest.java:
public class QAServiceTest {
#Test
public void getserviceTest () {
QAService qasmock = mock(QAService.class);
when(qasmock.getServiceInfo()).thenReturn("50");
String expected = "50";
assertEquals(expected, qasmock.getServiceInfo());
}
}
Junit will only run methods annotated with #Test, so add it
#Test
public void getserviceTest () {
QAService qasmock = mock(QAService.class);
when(qasmock.getServiceInfo()).thenReturn("50");
String expected = "50";
assertEquals(expected, qasmock.getServiceInfo());
}
Also, you should verify() that your mock expectations actually happened.
verify(qasmock, times(1)).getServiceInfo();
Note that it seems like you want to test QAService, but you really aren't doing that here. You are simply testing a mock. That's not the same thing.
Create the QAService object yourself and use it.
Let's get a couple definitions straight, first:
A unit test is a brief bit of code you write to ensure that the system you've developed is behaving correctly. Unit tests are often created in a framework like JUnit, but do not need to be. For example, a unit test would assertEquals(5, calculator.add(2, 3)).
A mock is an imitation of a real system, which is often used in unit tests. Mocks are often created in frameworks like Mockito or EasyMock, but do not need to be. Mocks are a form of "test double"—the general term for code you substitute in place of your actual systems, for testing purposes—and Martin Fowler defines them more exactly in an article called "Mocks Aren't Stubs".
When writing a unit test, you're trying to test a single unit, which is often called the system under test or SUT for short. Each test will probably have a different system under test, and the point is that the code that you are testing in the test is your real, actual code, not any sort of mock or fake implementation.
In a complex application, your classes will probably need to collaborate with other classes that may or may not be written or tested, which are categorically known as dependencies. Any given class or system may have its own dependencies, and may be a dependency for other systems. Mocking frameworks are good for mocking those dependencies, not for mocking the system under test.
For your example, QAService is the main class you're writing (system under test), and QAServiceTest is the unit test for that system. No mocks are necessarily required.
Let's say that QAService depends on another class not yet written, called "StorageService". You don't necessarily want to wait for StorageService to work before writing QAService's tests, so instead of using a real StorageService you use a mock. Again, in the unit test called QAServiceTest, you use a real QAService and mock its dependency StorageService.
Even though you don't have StorageService written, you probably have some expectation about how QAService will use that class. Maybe you know that when you call storageService.store(qaRecord), it should return a numeric ID like 101. Even without the code working, you can create a Mockito mockStorageService, and prepare it like this:
when(mockStorageService.store(expectedQARecord)).thenReturn(101);
Now let's say that at the end of the test, you want to ensure that the method of QAService that you're testing will absolutely call storageService.delete(101). A Mockito mockStorageService would check that like this:
verify(mockStorageService).delete(101);
It is often unnecessary to verify statements you have made with when, because the test is unlikely to succeed unless the system under test calls the mock correctly to get that return value (101 here).
Now let's say that you've written another block of code called QAApplication, which you're testing in a unit test called QAApplicationTest, that depends on QAService. You may not have QAService finished or tested, and using a real QAService would require a StorageService, so instead you use mock QAService with a real QAApplication in your unit test called QAApplicationTest.
So, to sum up, a mock works within unit tests to mock the dependencies of the system under test. In your situation, QAServiceTest will not need a mock QAService, but may be used to mock the dependencies of QAService. If you do need a mock QAService, you'll need it when testing another class where QAService itself is a dependency.

Java - Unit test cases for delegating class

I have a service class MyBusinessService with 2 methods doABC() and doXYX(). Method doABC() delegates the work to ABCHandler.do() and method doXYX() delegates the work to XYZHandler.do(). MyBusinessService class methods just delegates the works to corresponding handlers.
I have a question here. When i write Unit test for this, i must write unit tests for the methods in the handlers. Should i write UT for MyBusinessService class methods. I ask this question for 2 reasons.
a. With UT tests, one functionality should not be tested in 2 places. My actual logic is in handler classes and i should not unit test the same logic in both handler class and service class
b. If i dont write unit test for MyBusinessService class methods, then in the future if some developer makes some bug fix and breaks something, then it may cause the application to fail in production. So, i need a test here. But if i write test case for this class, this will break rule (a).
Please let me know whether i should write UT for delegating class(MyBusinessService class) or should i leave it to Integration test cases to address it.
Unit test must test only one class. If you test interaction of more than one class instances so you're doing integration testing. You should consider using some mock library like jmock or mockito, the first one fit better for my uses.
If you use jmock you can do as above:
#Test
public void someTestMethod(){
MyBusinessService instance = new MyBusinessService()
Mockery context = new Mockery();
ABCHandler mock1 = context.mock(ABCHandler.class); //creating a mock object
instance.setABCHandler(mock1);
context.checking(new Expectations(){{
oneOf(mock1).do(); //creating a expectation wich expects exactly on call of method do.
}});
instance.doABC();
context.assertIsSatisfied(); //check if the expectation is met
}

include test in source file java

I Want to write my unit test in the same source file being tested (like you can do in D http://dlang.org/unittest.html).
I also want to be able to run the test in eclipse as i usually do with a dedicated test file.
In this example Junit complains if there is no public zero argument constructor:
public class Dummy {
private String _name;
public Dummy(String name) {
_name = name;
}
public String name () {
return _name;
}
#Test
public void testName() throws Exception {
assertEquals("dummy", new Dummy("dummy").name());
}
}
Any suggestions on how to put the test method in the "real" source code and be able to run the test (in other words how to fool the no arg constructor restriction)?
Thanks
You could consider classical TDD (based on Kent Beck's book "Test Driven Development By Example"), where the idea is not to write tests for specific classes/methods, but rather for features that you want to implement.
That way, it really doesn't make sense to put tests in production classes.
To run the JUnit Test framework, it internally requires a zero argument constructor to instantiate it. Generally it creates by default, if you don't have any constructor. But since you have one constructor with argument, the framework will not be able to instantiate the respective class to execute the test case. To avoid it create a blank no argument constructor.
Having test methods in the same class is not possible with JUnit and is also a quite strange design choice. Well, it would be possible if you had a zero argument constructor, but still, a test class is not meant to be the class that is tested. However, you can create a test class in the same file to carry out your test cases.
You can create a second constructor without parameters if you really want to put your JUnit tests inside the same class. Nevertheless this is not the way you do it according to the java conventions.
Also it bloats the class with unnecessary test cases (unnecessary for the actual task the class should do). You should maybe think about it if it would not be better to put the test cases in a separate class.
You can write your own Runner instead of using JUnit's default BlockJUnit4ClassRunner. Please let me know if you need help.

What's the best way to unit test classes that delegate the work to others?

I have a question about how best to tackle JUnit testing of a top level class. Imagine I have a class, SomeWriter, that has a method that reformats a String and writes it to a stream. The method doesn't actually do the work but instead delegates it to a member object that actually does the real work. I've summarised this in the class below.
public class SomeWriter {
public void writeReformattedDataToStream(OutputStream outStream, String message) {
myReformatter.DoTheActualWorkAndWriteDataToStream(outStream, message);
}
}
Now in this hypothetical example, I've already written my unit tests for the myReformatter class and I've demonstrated that myReformatter works. My question is, how should I tackle the unit testing of the writeReformattedDataToStream in SomeWriter?
If I were black box testing, I would need to write the same test as I applied to the myReformatter class because I wouldn't know how it implements the task. However, unit testing is really white box testing, so is it valid for the test merely to ensure that myReformatter is being correctly called?
The bottom line is should my test of writeReformattedDataToStream effectively repeat the test of myReformatter, or mock myReformatter and just check it's being called correctly?
I appreciated this is similar to JUnit Test - Class invokes methods in other class
Immediate delegation like this usually falls under the heading of "too simple to test", but if you have some absolute requirement for it, then you need to mock your OutputStream (using EasyMock or a similar tool) and myReformatter and verify that the delegate calls the appropriate method.
As chrylis says, you should not test this method.
There is actually nothing to test.
If you write a test case that tests that the delegate / service is called, then your test is bound to the implementation of the tested method.
So any change in the implementation of the method would require to change the test; and I am sure that you do not want that.
Try injection. For testing purposes you could inject your own implementation of the myReformater class that simply checks that the method was called correctly and returns. Then you are testing your test class in isolation.

JUnit: new instance before invoking each #Test method. What are the benefits?

Currently, I am reading "JUnit in action" book. In this book I found text below:
JUnit creates a new instance of the test class before invoking each
#Test method. This helps provide independence between test methods and
avoids unintentional side effects in the test code. Because each test
method runs on a new test class instance, we can’t reuse instance
variable values across test methods.
Now I do not see much point in this approach:
For example:
public class CalculatorTest {
#Test
public void testAdd_1() {
Calculator calculator = new Calculator();
double result = calculator.add(1, 1);
assertEquals(2, result, 0);
}
#Test
public void testAdd_2() {
Calculator calculator = new Calculator();
double result = calculator.add(2, 2);
assertEquals(4, result, 0);
}
}
For test class CalculatorTest there are no any benefits.
Ok, lets go pay attention on another example:
public class OneTest {
static byte count;
public OneTest() {
count++;
}
#Test
public void test1() {
System.out.println(count);
}
#Test
public void test2() {
System.out.println(count);
}
}
For test class OneTest I found a way to use the same variable count for the many test methods...
so, How to see the real benefits of the approach described in the book?
How to see the real benefits of the approach described in the book?
The purpose of separate instance is not for any benefit but to maintain the contract that each test should be independently executed without any effect of the execution of a previous test. There is just no other way to ensure this contract other than using a different instance for each test.
For example, the Spring transaction management makes sure to rollback all changes made to the database by a test, by default, to maintain the same contract.
So, using static variables in a test is generally discouraged as it will defeat the whole purpose of one-instance-per-test to have a clean slate for each test.
Keeping the state clean between test methods is useful for unit tests but gets in the way for functional tests, where having dependencies between tests is often necessary (for example, when you are testing web pages using Selenium, it's useful to not bother running tests of a certain page if the tests for the login page failed).
This was one of the main reasons why I created TestNG, which doesn't instantiate a new class between each method, therefore giving you the choice instead of imposing this decision on you.
TestNG also supports dependencies of tests, multithread testing, has the notion of groups ("only run the servlet tests") and many more features.
If you're testing a mutable class, there's great value in having your tested object in a known state at the beginning of each test method, so that the order of test execution does not matter. The easiest way to accomplish that is to create a new instance of that class for each test, and to avoid static fields.
In your calculator example, it appears that your Calculator class is immutable and the results of method calls depend only on the parameters. So the risk of one test influencing another is just not there.
I don't quite see the point of your second example. You've written methods annotated as #Test that use a shared static field, but your methods have no assertions, and are not really testing anything.
If you want to do use static fields or indeed to hold onto and reuse a single instance of the class under test, it's certainly possible to to so, but to make your tests work and stay independent of each other will tend to require more care.

Categories

Resources