How can i test several .java files(that implements the same method in different ways) with one unit test?
For example, i have a folder with different .java files(or different folders with the same name .java file), how can i select all of them to run it?
right now i need to select each time one of them and move it to the same folder with the unit test and run it.
Thanks.
Edit: I think i wasn't clear enough, so i will give more example:
I have files aa.java and bb.java, which both have the method "static public int fibonacci(int x)", i want to create a unit test, that will use aa and bb methods and see if they work properly(assertEquals(result, expected)).
P.S. i have more then only 2 files with the same method.
Assuming you want to adhere to DRY, write a utility method to do the testing, and have a unit test(s) call it.
Eg
private static void assertFibonacci(IntUnaryOperator op) {
int n = 5;
int expected = 8;
// or a loop of values, whatever
assert op.applyAsInt(n) == expected;
}
Then in your unit test:
#Test
public void testX() {
assertFibonacci(new aa()::fibonacci);
assertFibonacci(new bb()::fibonacci);
}
Or better, use separate Test methods, so errors in each are reported separately:
#Test
public void testAA() {
assertFibonacci(new aa()::fibonacci);
}
#Test
public void testBB() {
assertFibonacci(new bb()::fibonacci);
}
The Spock Framework, which runs on top of JUnit, has much better support for parameterized testing, which is what you seem to want, than either plain JUnit or TestNG.
If you can't use Spock, you can either use JUnit Parameterized and supply an instance of each of your classes as your data set, or (my recommendation) write all your common unit tests in an abstract base class WidgetTests with a method protected abstract Widget getInstance() and subclass for each kind of widget. This will still end up with multiple classes, but you won't repeat your test cases, and it allows you to write additional implementation-specific tests in an organized way.
Related
I have a private method in my java code which needs to be invoked twice. I am writing junits using Powermock. While mocking the said method I need two different results for two different invokations.
//I have tried:
PowerMockito.doReturn("MyString1").doReturn("MyString2").when(spy,"getresult",Mockito.anyString());
//But when() is not accepting anything else than the spy object.
PowerMockito.doReturn("MyString1").doReturn("MyString2").when(spy).getresult(Mockito.anyString());
//when() is not letting to use the method getresult as this getresult method is declared private.
CODE
Class A{
String firstString="abc";
String secondString="def";
String result1=getresult(firstString);
String result2=getresult(secondString);
private String getresult(String arg1){
//My code here;
return "AnyString";
}
}
JUNIT
//Declarations
#InjectMocks
A a;
.......
#Test
public void ATest(){
....
/*Suppose I want "MyString1" and "MyString2" as result for calling the method "getresult" for result1 and result2 in Class A*/
A spy=PowerMockito.spy(a);
PowerMockito.doReturn("MyString1").when(spy,"getresult",Mockito.anyString());
....
}
// Please overlook the typos
I am getting compilation error while using the code that I tried.
As written in the comments of code, I am expecting two results "MyString1" and "MyString2" in the two successive method calls as shown in the code.
Thanks in advance. Any other approach to achieve the results is appreciated.
Let me start with the note that the main reason to use PowerMock is to help testing the Legacy applications. There is literally no place for the PowerMock in a new code. Need for a PowerMock in a new code indicates serious problems in the design.
One of the benefits of unit testing is that the tests provide feedback on your design. If writing such test is overly awkward, fragile or not possible (without PowerMock) you should reconsider your design.
One of the things you can do to test such code is to extract the private method into a separate class and provide it as a dependency. Then you can mock it easily. But you should still test the extracted logic which depends on why you could not setup the test in the first place. You may need integration test or some other approach.
I usually do not test private methods separately. They will be tested by the public method which is calling this private method. If there are multiple flows, write multiple tests in a way where all code paths in the private method are tested.
However the following link shows how to test private methods.
https://dzone.com/articles/mock-private-method
class Elephant extends Animal {
public Elephant(String name) {
super(name);
}
void makeNoise() {
logger.info(" Elephant make Sound");
}
void perform(String day) {
if (day.equals("thursday") || day.equals("friday")) {
makeNoise();
}
}
}
Now i want to test the perform method. How can I unit test this method using JUnit?
Solution with Mockito Spy
import org.junit.Test;
import static org.mockito.Mockito.*;
public class ElephantTest {
#Test
public void shouldMakeNoise() throws Exception {
//given
Elephant elephant = spy(new Elephant("foo"));
//when
elephant.perform("friday");
//then
verify(elephant).makeNoise();
}
}
Negative tests:
#Test
public void elephantShouldDontMakeNoisesOnMonday() {
//given
Elephant elephant = spy(new Elephant("foo"));
//when
elephant.perform("monday");
//then
verify(elephant, never()).makeNoise();
}
or
#Test
public void shouldDoNotMakeNoisesOnMonday() {
//given
Elephant elephant = spy(new Elephant("foo"));
//when
elephant.perform("monday");
then(elephant).should(never()).makeNoise();
}
Dependency
org.mockito:mockito-core:2.21.0
Read about
Mockito#doNothing()
Mockito#spy(T)
void() functions change the state of a program. This can be done by modifying a variable, a file, a database, etc.
In your case you're writing to a logger. If this results in writing " Elephant make Sound" to a file then you can read that file and see if the data in the file includes your noisy elephant.
If it however doesn't involve anything you can check (i.e.: it simply displays the output on the console) then you might want to look at some form of dependency injection (DI) where you can set the output to a file or something else you can easily read.
It should be noted that you can bypass DI by mocking the object and checking the appropriate methods are getting called.
To test any method, the responsibility to be tested must be visible from the out side of the method by changing state of any variable.
Typically it is done by returning value from the method. But without that, it can be done in many ways by modifying something from outside of the method scope, in case you have any "problem" to return something from the method!
In your case, you only log some message. And your code is not really testable in a sense that it does not do something that is directly related to changing the state of any variable (Because you change the state of other resource other than variable, that is not directly accessible by your code. You have to write some code to read the changes from that external resource, hence makes your testing code dependent to the reading also. If you have some problem with reading, your test case will not pass and that does not go with the spirit of the unit testing. The main idea is to reduce the dependency on external codes or libraries as much as possible). But your code can be testable by doing a slight refactoring / shifting responsiblity like below:
String makeNoise() {
return "Elephant make Sound";
}
String perform(String day) {
if (day.equals("thursday") || day.equals("friday")) {
return makeNoise();
}
}
And then you shift the responsibility of logging the value returned from perform method to the one using it like below:
logger.info(perform(day));
You have various options depending on the tools you are willing to use and the depth your tests should have.
Partial Mocking with plain Java
Create a class (MockElephant) that extends from elephant, overwrite makeNoise so it counts the number of invocations. Use that class in your test to check that makeNoise was called the correct number of times
Partial Mocking with a Framework
You basically do the same as above but instead of manually coding the MockElephant you create it using some mocking framework. Makes the test much simpler, since you need less code. And it is easier to read. But if strange things happen it makes it harder to understand what is going on. In case of Mocking frameworks I think they are worth it.
The reasons why this is called Partial Mocking is that you mock only parts of a class (a single method in this case).
The alternative is to use Normal Mocks, which in your case seems feasible (but can become tough in legacy code).
Here you would inject the Logger as a dependency. For example you could create an additional constructor which allows you to provide the Logger. In your test you would then use a mocked Logger, which again counts it's invocations, probably along with the parameter it received and check that it has the expected values.
Again you can do that with a Mocking Framework or with plain old Java.
I have this problem. One class (and actually with one public method) to test, and ~30 test scenarios stored in the separate xml files. As one unit test class would be too long (need to test all the files in separate test), I decided to divide them into few groups (few classes), and now the questions occur.
The unit test itself implements few other methods, used in testing (for getting resources, formatting calendar in different matter), as I got few of those unit classes I should also copy those methods.
I just thought if I could create additional class for the methods, and use simply inheritance, or maybe I should create each unit test with the those copied methods? What is the good practice in such a case?
An alternative to inheritance is delegation, as mentioned by Alan Stokes. A good way to make use of this in junit is: use Rules. Some are provided, but you can rather easy create your own set of rules.
The major benefit we have experienced is that you can cherry pick the common features you want to have. Sometimes you just want a tiny bit of the common abstract test class. But as you can only have the full set or nothing, you may end up setting up a database state for a rather simple unit test.
In the sample below from the junit Wiki the TemporaryFolder Rule adds the ability to the test to create temporary folders and files. Those will be deleted after every test execution.
public static class HasTempFolder {
#Rule
public TemporaryFolder folder = new TemporaryFolder();
#Test
public void testUsingTempFolder() throws IOException {
File createdFile = folder.newFile("myfile.txt");
File createdFolder = folder.newFolder("subfolder");
// ...
}
}
Another good thing about it is that you can change the behaviour to class level rather easy. A situation where you might want to have this is the setup of an expensive fixture state in a database or search index. Or when you create a big sample XML for some ETL process for which you want to run an integration test. This should be used only when performing read only operations.
To move it to class level, you just need to make the member static and add the #ClassRule annotation instead of #Rule
public static class HasDataBaseState {
#ClassRule
public static DataBaseState dbState = new DataBaseState();
#Test
public void testUsingDataBaseState() throws IOException {
// perform tests
dbState.query("select count from table where attribute = 'x'");
}
}
There are more features, but those are covered rather good on the junit wiki. The facts I pointed out are the ones we like most about it.
If you need common test fixtures for a number of different test cases, it's perfectly fine to use an abstract base class for your unit tests. For example, small-scale integration tests using Spring will often use a base class that sets up the test runner and context and then add the specific components they're testing.
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.
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.