Solved

Unit Testing a C# or Java function in NUnit or JUnit which doesn't take an input argument. How to

Posted on 2013-01-27
5
917 Views
Last Modified: 2013-12-13
Hi there;

I have been trying to test my functions which I wrote in C# and Java, but when the function takes no input argument and calls other functions in it. I have no clue how I can arrange the test functions. This is same in C# and Java. I am using NUnit and JUnit respectively.

I have 3 basic problems actually:
1) What if the function to be tested receives no input arguments
2) What if the function to be tested calls other functions (should I test the other functions individually or within the target function?)
3) No return values or global variables such as ArrayLists or Dictionaries..

Following code covers, the first 2. I want to test some dummy files apart from the List.txt file, but I don't know how I can set the test case since the filepath is not passed and is not even global to the class..

 public bool Read()
        {
            string line;
            alist = new SortedDictionary<string, string>();

            using (StreamReader sr = new StreamReader("List.txt"))
            {
                while ((line = sr.ReadLine()) != null)
                {
                    try
                    {
                        // Splitting line into atoms where the first atom represents prefix, and third atom represents a operator numerical code                                                        
                        if (!line.StartsWith("O"))
                        {
                            string[] atoms = line.Split(new char[] { ' ', '\t' });
                            Prefix = atoms[0];
                            Price = atoms[2];
                            Search();
                        }
                        else
                        {
                            Display();
                            alist.Clear();
                            Letter = line[line.Length - 2];
                        }
                    }
                    catch (FileNotFoundException e)
                    {
                        return false;
                    }
                }
                sr.Close();
                return true;
            }
        }

Open in new window


Test case is as follows:

 [Test]
        public void CanRead_Absolute_Path()
        {
            // Arrange
----------->            string path = "ListEmpty.txt";  I cannot pass the file name...What should I do? Should I read it?
            var target = new Routing();
            var expected = true;

            // Actual
            var actual = target.Read();
----------->when you check above read function, there are display function and a arraylist clearing...How can I populate this?
            // Assert
            Assert.AreEqual(expected, actual);
        }

Open in new window


Regards.
0
Comment
Question by:jazzIIIlove
  • 3
  • 2
5 Comments
 
LVL 12

Assisted Solution

by:topdog770
topdog770 earned 500 total points
ID: 38827986
Hi Jazz,

All good questions!  In some ways, your questions and the situations you have encountered  demonstrate the benefits of doing tests like this.

General Statement #1 - This shows one of the reasons why creating test cases before creating the actual working code is so beneficial.  Most likely you would have crafted the code differently to avoid this situation.

If I was setting up tests to determine if this code was performing as expected, I would have to re-architect the code a bit.

The return code of the method must tell us something useful, this return code doesn't clearly indicate that the code peformed correctly.  It may have--you would probably know that as the author but the code doesn't, and reading this code won't tell us, because we see that Search() does not have a return value neither does display.  Effectively, this means that even by creating a test case for this code, we will never know if it really worked as expected.

I would change the code to have the ability to store and specify the name of the code.. either in a property or as a parameter to the Read() method, depending on what makes the most sense for the work done by this code.

Now, with that change, you CAN test the code in scenarios where both the file exists and where the file doesn't exist.

And, now, your tests start to be become powerful!  

Immediately after setting up this test, I realize that I can pass in a valid file path, but if the file has no contents, the method could still return true, so perhaps this another test and additional logic that can be added to the method.

In short, just the process of starting to create these tests has helped you highlight some very useful changes to your code that will make it more effective and give you greater confidence in its ability to do the work you designed it to do.


To answer your specific questions--

1) You can still test a method that does not accept input parameters.. but if it's code like you show above, then creating useful tests against it are very limited.
2) When creating the tests on code that is already written, I like to start from the very top and work my way down (there are risks to this approach, but especially when you don't know the code very well, it's a great approach..and as this sample code shows.. starting at the top of the code can make it easy to identify improvements that will trickle down to the other methods as well.  The first tests that I would have created on the Read method would identify additional tests and probable restructuring to the Display and Search methods that I would make next.

3)  No return values provides limited options and probably indicates an opportunity to improve the code.

For global variables, you can set or measure their values before the method to be tested and then evaluate the global variables after the method to be tested is complete for the expected result to determine success.
0
 
LVL 12

Author Comment

by:jazzIIIlove
ID: 38829572
Hi;

Thanks for the comment. Ok, let's see. Following is another code segment, this time in Java and Junit:

It's straight forward, reads a file and inside this function, another function call is made.

public boolean read(String filePath)
	{
		try{
			// Open the file that is the first command line parameter
			FileInputStream fstream = new FileInputStream(filePath);

			// Get the object of DataInputStream
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));

			String strLine;
			//Read File Line By Line
			while ((strLine = br.readLine()) != null)   {
				split(strLine);				
			}			
			//Close the input stream
			in.close();
			return true;

		}catch (Exception e){//Catch exception if any
			System.out.println("Error: " + e.getMessage());
			return false;
		}
	}

Open in new window


The problem is that split() function causes null pointer exceptions. I just want to skip that line as nothing happens in JUnit. Possible? I googled a lot but couldn't find out any example. Can you help?

Is it the "mock"ing thing in testing world?

Regards.
0
 
LVL 12

Author Comment

by:jazzIIIlove
ID: 38829627
Hi as an update;
I installed mockito jar and try to invoke doNothing function as follows:
      public void readTestRegularTextFile()
      {
            // Arrange
            Routing r = new Routing();            //read and split functions reside in this class
            Mockito.doNothing().when(r).split("");            
            boolean actual = r.read("List.txt");
            boolean expected = true;

The problem is that it's not working, and moreover, the split(..) function content changes for every line read. So, what to do? I am just trying to proof the files are read.

Regards.
0
 
LVL 12

Accepted Solution

by:
topdog770 earned 500 total points
ID: 38831295
So to prove that the files are being read using a known file, I would do something like this:

set the expected to be a copy of the contents of the file to be read

string expectedResult = "a literal version of the file contents that are to be read";
string actualResult = File.

read the whole file into a buffer and confirm that the expectedResult is equal to the actualResult

For the splitting functionality, you could do the same thing.  Set up a string literal value or string [] of literal values and confirm that reading the actual file gives you the same results.

I would try to figure out the null pointer exception issue as will.
0
 
LVL 12

Author Closing Comment

by:jazzIIIlove
ID: 38845347
Good points. Thanks.
0

Featured Post

Backup Your Microsoft Windows Server®

Backup all your Microsoft Windows Server – on-premises, in remote locations, in private and hybrid clouds. Your entire Windows Server will be backed up in one easy step with patented, block-level disk imaging. We achieve RTOs (recovery time objectives) as low as 15 seconds.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
topping2 challenge 13 58
advertisement module in core php 4 81
C# Update Status Bar.... 1 24
Achieve json result 2 28
A high-level exploration of how our ever-increasing access to information has changed the way we do our jobs.
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Video by: Tony
This video teaches viewers how to export a project from Adobe Premiere Pro and the various file types involved.
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now