Unit testing for java program [closed] - java

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a Java program which reads the contents of a file containing a list of numbers, picks out numbers which have been duplicated and writes them to the console.cant figure out where to put them or what they should look like.
import java.util.;
import java.io.;
public class ReadAFile {
public static void main(String[] args) {
String list[] = new String[];
FileInputStream fstream=new FileInputStream("C:/Users/Kevin/Desktop/testfile.txt");
// Use DataInputStream to read binary NOT text.
BufferedReader br=new BufferedReader(new InputStreamReader(fstream));
String str,str1;
int i=0;
while((str=br.readLine())!=null){
i++;
str1=Integer.toString(i);
if(lines.containsValue(str)){
System.out.println(str);
}
in.close();
}
}

you need to think of a test-case, write a test-class, and put it under /src/test/java directory.
Then you need to write some methods inside test-class(separate method for a testcase is common way), annotate that method with #Test annotation and run maven

You can look at this tutorial here!, it very thorough providing details about how to run Unit tests in Eclipse and making use of EasyMock.

First step would be to organize your code in units so that each unit can be tested. In Java world, this unit would be a method in your class. So first step, write your code in a method other than 'main'.
Next, you write a program which tests the method you wrote. Basic structure of such a program would be
1) Do anything which is required to run the method under test.
2) Run the method
3) Observe the output to verify if it produced correct results.
JUnit is a Java library which makes it easy for your write such tests by providing some pre-canned methods.
You have the basics now, rest, as they say, can be googled.

Really straightforward tutorial is here from mkyong it worked really well for me when I started with unit tests. Also some mocking for the Input Output manipulation will be handy.

Unit tests in a maven project usually are located in a separated source folder /source/test/java. Maven automatically executes all tests found at this location.
To test your class you would have to refactor it so you can set the path to the input file to an test file that you may place in /source/test/resources for instance. At least if you want to write an integration test that verifies the reading of the input file.
The processing logic that identifies and prints duplicated entries may be tested via a "real" unit test that somehow mocks the BufferedReader and provides some test data without reading it from a file. Here easymock may be one library you can use.
To simplify the testing of your class your may put all your logic in a non-static method and call it from your main method by creating an instance of the class itself.
public class ReadAFile {
public static void main(String[] args) {
ReadAFile instance = new ReadAFile();
instance.readAFile(args[0]);
}
public void readAFile(String fileToRead) {
HashMap<String,String> lines=new HashMap<String,String>();
...
}
}

As you already has included junit in your project, you have to think in the following structure for unit testing.
You will have for each class you want to test, a correlative class to test it, so MathTest will unit test Math class
Then, imagine you modify your code to have 2 methods, one for read a file, one to parse the InputStream and one to showResults.
Here is an Interface I would use, but take it just to know the method declaration.
public interface MyCodeToBeTested {
List<String> parseFile(final String path);
void processLines(List<String>);
}
Imagine you implement this interface with a class named ImplementedClass.
So you can have a Junit class which test each of the methods looking for fails.
import junit.framework.Assert;
import org.junit.Test;
public class Tester {
#Test
public void testReadFile() {
ImplementedClass myclass = new ImplementedClass();
List<String> lines = myclass.parseFile("mytestfile1.txt");
Assert.assertEquals(3, lines.size());
Assert.assertEquals("this is the first line of the file", lines.get(0));
}
}
With this test you check that parsing a file works fine, one time you are confident with your read file though unit testing, you can move to test the processLines method without taking care of the file.
#Test
public void testProcess() {
ImplementedClass myclass = new ImplementedClass();
List<String> lines = initializeLines();//initialize your lines
myclass.processLines(lines);
//Assert here myclass results
}

Related

How to sequentially execute 2 Java classes via mvn command

I have 2 Java classes which have a symbiotic relationship.
Class 1 produces some output files and Class 2 consumes the output of class 1 and validates it. Both of these classes take input from the commandline. This project is maven based.
Given this symbiotic nature, I am unsure how to "connect them"?
My thinking was, to write another Java class which takes in command line inputs and calls the 2 classes. However there is another uncertainty here, how could I run class 1 (in order to produce the output files) so then I can have class 2 to validate it. Perhaps Junit #Before or some annotation? I really am unsure how to proceed. I hope I am making sense here.
Any help or suggestions would be much appreciated.
Execute the main() method of your class under test from within a JUnit method.
public class Class2 {
#Before
public void produceOutputFiles() {
Class1.main(new String[] { "these", "are", "commandline", "arguments"});
}
#Test
public void validateClass1Output() {
//read in the files and validate the output
}
}
Invoking Class1 via Process.exec() is an option with many downsides. It is much simpler to keep both the test and the tested code within the same JVM.

Should I repeat code in actual class in tests

I want to test that a specific method produces the expected result, but to do that I need to manipulate the input in the test as well.
class ToTest {
public String produceResponse(String input) {
// ....
encryptedIds = encryptIds(input)
output = doStuff(input, encryptedIds)
}
public encryptIds(input) {
....
}
}
In my test I need to check that produceResponse actually produces the expected response.
in order to do that I have to encrypt the ids in the input.
My question is: should I rewrite encryptIds in the test (so that I would have more controller on the result) or should I call encryptIds from the class itself.
Is there a better approach to solve this? I don't like that in my test I know what happens in the specific flow.
If I understand correctly, you would like to test produceResponse() with known encryptedIds as input.
You could do that without refactoring the code, but it would probably be a good idea to refactor it, so that's what I'm going to explain:
class ToTest {
private IdEncryptor encryptor;
public ToTest(IdEncryptor encryptor) {
this.encryptor = encryptor;
}
public String produceResponse(String input) {
String[] encryptedIds = encryptor.encryptIds(input);
return doStuff(input, encryptedIds);
}
}
Now you can unit-test IdEncryptor to test that it produces correct encrypted IDs based on a String input.
And to test the ToTest class, you can mock the IdEncryptor so that whatever the input it receives, it produces the encryptedIds you desire. For example with mockito:
IdEncryptor mockEncryptor = mock(IdEncryptor.class);
when(mockEncryptor.encryptIds(any(String.class)).thenReturn(new String[] {"a", "b"});
ToTest toTest = new ToTest(mockEncryptor);
String response = toTest.produceResponse("input");
// expect that the response is what you expect given "a", "b" as input of doStuff()
Never copy any production code into the unit test as it will get outdated at some point.
If both methods are public, they are part of the public API, so:
you should first unit test the correct behavior of the encryptIds(String) method
then unit test the produceResponse(String) method which will internally use the already tested encryptIds(String) method
If encryptIds(String) would not be part of the public API:
then it is internal implementation and helper method which is not unit testable
produceResponse(String) is then responsible for encryption as a side-effect:
you can still test it if you mark it package private (no modifier)
you can also change the implementation of the encryptIds(String) only for testing purposes
Is encrypting id's something that is integral to your system or not? As it stands this class takes some input and produces some output and as far as your test is concerned this is what's important, no more, no less.
What is the impact of not performing the encryption? If your doStuff method will just fail if it doesn't happen then it is an internal detail to your class-under-test and I wouldn't have the tests care about it at all. If it's a step that absolutely must be performed then I would refactor the code to verify that it absolutely has happened, maybe using a mock as #jb-nizet answered.
As for the general case of duplicating production code in tests, as #Crazyjavahacking stated you should not do this, but I have no issue with using production code from a test- maybe not at a unit level but definitely the higher up the system I go, e.g. when testing writing to a DB I will use the reading code to verify it's happened correctly, but will also have independent tests to verify the reading path as well

How do I create pre-formatted Java files in Eclipse?

I am currently writing JUnit test cases using the Selenium-RC API. I am writing my scripts like:
//example JUnit test case
public class myScripts extends SeleneseTestCase {
public void setUp() throws Exception {
SeleniumServer newSelServ = new SeleniumServer();
newSelServ.start();
setUp("https://mySite.com", "*firefox");
}
public void insert_Test_Name throws Exception {
//write test code here
}
}
And for each test, I have a new JUnit file. Now, since the beginning of my JUnit files will all basically be the same, just with minor variations towards the end, I was thinking about creating a pre-formatted Java template to write create a file with the redundant code already written. However, I can't find any information on whether this is possible. Does Eclipse allow you to create file templates for certain packages?
Create a super class to add all the common code. Creating template is really bad because of the fact you are duplicating the code at the end of the day.
class Super extends SeleneseTestCase{
// Add all common code
}
class Test1 extends Super{
// only special test case logic
}
Also I would suggest not to create SeleniumServer instance for each test case, It will reduce overall performance of the test suite. You can reuse object as long as you are running test sequentially.

Clarification in Java Code Testing

I have started reading the Spring in Action book.
I have no knowledge of JUnit which I think my doubt is about.
There is a code fragment where the author refers to and says that it is difficult to test:
package com.springinaction.knights;
public classDamselRescuingKnight implements Knight {
private RescueDamselQuest quest;
public DamselRescuingKnight() {
quest = new RescueDamselQuest();
}
public voidembarkOnQuest() throwsQuestException {
quest.embark();
}
}
The author says that:
It’d be terribly difficult to write a unit test for DamselRescuingKnight. In such a test, you’d like to be able to assert that the quest’s embark() method is called when the knight’s embarkOnQuest() is called. But there’s no clear way to accomplish that here. Unfortunately, DamselRescuingKnight will remain untested.
What does the author mean by this?
Why is the code difficult to test here?
My initial thought is that it is difficult to test because the "RescureDamselQuest" object is initialized in the constructor. This makes it difficult to for example insert a mock object. A mock object would help you test that the embark() method is called on the "RescueDamselQuest" object.
A better way to solve this can be to either include a parameter in the constructor (usually I prefer this method):
public DamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
Or add a setter:
public void setDamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
A common example I give is consider that you want to open a file, parse it, and get a data class out. Most will do something like:
Data openAndParse(String filename) {
...openFile
...parse
}
By doing it this way, the file open methodology and parse is highly coupled and difficult to test. If you have a problem in open and parse is it with the parse or the open?
By writing JUnit test, you are forced, for simplicity sake, to do something like...
BufferedReader openFile(String filename) {
...open file and return reader
}
Data parse(BufferedReader input) {
...parse and return data
}
JUnit leads us to a more cohesive solution. We write JUnit test simply by creating a string, constructing a StringReader, and then a BufferedReader. Well guess what? Very similarly we can now use parse to accept input from a variety of sources not just the file.
It's difficult to test because the quest implementation cannot be swapped out. Without byte code modification there's no trivial way to see if embark is called.
If you could set the quest implementation in a constructor or setter you could pass in an implementation that can spy on the call to embark.
One need to increase accessibility of fields and method of class to test. For example if one is testing a method which is package-private (default) then test cases which are generally in different package will not able to test this method. Therefore it is advised to to change in accessibility of fields to test the method. DamselRescuingKnight class can be tested which is not using DI by modifying the accessibility of RescueDamselQuest field from private to default. Then writing test case using mockito. Here is code for test case
#Test
public void knightShouldEmbarkOnQuest() throws QuestException {
DamselRescuingKnight knight = new DamselRescuingKnight();
RescueDamselQuest quest = mock(RescueDamselQuest.class);
knight.quest = quest;
knight.embarkOnQuest();
verify(quest, times(1)).embark();
}
And line which was changed in DamselRescuingKnight class to remove private accessibility
RescueDamselQuest quest;

How do I test this method in this class to see if it's working but it has no main in it [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
So this is link below the class and it has no main method and I am trying to test and see if every line in the methods[[1]:][1] is processing and if not where is it getting errors.
What you're looking for is JUnit, or, more specifically, the site under "Getting Started" there.
For short, if you had a class Dog with a method like this
public boolean isBrown() {
// some hard & heavy logic
}
you'd probably like to see whether it works or not. To do that, you'd create a test package within your application with some testing classes, one of them could should be named DogTests and contain this:
public class DogTests {
#Test(expected = NullPointerException.class)
public void nullDogShouldFailWithNpe() throws Exception {
new Dog(3, 14, null);
}
#Test
public void brownDogShouldBeBrown() throws Exception {
Animal animal = new Dog(3, 14, "brown");
assertTrue(animal.isBrown());
}
#Test
public void greenDogShouldNotBeBrown() throws Exception {
Animal animal = new Dog(3, 14, "green");
assertTrue(animal.isBrown());
}
}
You can find documentation on those assert methods here.
Can you see the #Test annotation above the method? That is a JUnit 4 construct that says "Hey, I'm a test method. When running tests from this class, run me, too!" There's no need for main() method here - when you'll try to "run" the containing class, your IDE will notice all the #Test annotated methods itself, run them, and show you the test results.
You can even arrange multiple test suites, run the tests concurrently, run them automatically on building the application and all other sorts of testing magic... Start with this, dig on the website and you'll soon discover more of the unit testing goodness.
When the methods being tested are non-static, you first construct the object and then you can call the methods. If your JUnit test case is in a package of the same name as the class being tested, you can access both public and protected members. Here's an example test against the HashMap class which has no main method.
public void testDuplicateKey() throws Exception {
HashMap<String,String> map=new HashMap();
// setup
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
assertEquals(3, map.size());
// overwrite an existing key
map.put("key2", "value4");
assertEquals(3, map.size());
assertEquals("value4", map.get("key2"));
}
Use BlueJ. It lets you work with objects without any Main methods present.
Simply import the Java file(s) to the IDE and right-click on the Class Diagram presentation of the class you get, to make objects of it. The IDE is very basic and user-friendly in that it works a lot in picture representations of classes and objects.
When you have an object of the specified class or classes, you get objects at the bottom of the IDE which you can right-click on to interact with. Good luck.

Categories

Resources