Issues in Writing Junit Test cases

1.2k views Asked by At

I have been asked to write a junit test case for a Listener.class. The listener pools for a directory and if there is any request the request gets processed.

The issues that I was facing is

  • many methods inside the Listener.class are private or protected.
  • Listener is a thread, and it does not get started just like that. Before the listener starting initializations and many other tasks are to be performed.

Progress until now:

Another issue that I am facing is inside the listener class if a method is called, it internally invokes another method, which will be using some some instance fields which are private or protected and theses field values are set by another classes.

On searching many blogs and looking at many questions I came to a conclusion that we need to write a mock of the previously called classes and mimic those behavior . I started creating the mock class by creating a new class, which performs the tasks prior to Listener start-up. Now my seniors are telling that its not the way to proceed and all that I am doing is creating a new server and these codes are not tested.

So how do I test the code?

My program flow is something like this.

  1. ServerConfiguration.class -> where configuration of the system is checked, jav-verion etc.
  2. reads Server.xml
  3. ServerService.class -> Makes a list of all the listeners,adapters and stores those in an hash map, Configures the ports for listener and adapters
  4. Serverservice.class-> Now starts only those listeners which are marked active in the .xml.

In my case Listeners are runnable interface. and they are instantiated by a thread,

Kindly give me your inputs.

UPDATE

Now my issue is, how do I run a test case for a method, when it is using variables of super class.When I run a test case it will always fail as these values are not initialized. How do I proceed next?

private boolean params()
      {
        String integrity = "";
        String sWAnswer = "";
        try
        {
          try
          {
            integrity = super.getParam("CHECK_INTEGRITY");
            sWAnswer = super.getParam("WRITE_ANSWER");


            **Some Business Logic** 

          super.info("Request Directory  : " + sRequestPath);
          super.info("Response Directory : " + sResponsePath);
          super.info("Error Directory    : " + sErrorPath);
          }
        }
        catch (Exception ex)
        {
          bCheck = false;
        }
        return bCheck;
      }
1

There are 1 answers

5
Jeff Neet On

It's been a while since I used EasyMock, but you may want to look into Partial Mocking Also I'm assuming by ".class" you mean ".java".

I think the underlying issue is that a unit test should be designed to test one small feature of code. What you are describing sounds like it is turning into an integration test. So first, make sure you have defined which type of test you are trying to write, both can be written using the junit framework.

Typically, you will minimize the use of mocks or not use them at all for an integration test because you are testing that all of your pieces fit together correctly.

For a unit test, you want to isolate a piece of business logic and ignore the rest of the system which is what using mocks allows you to do. The basic idea is to use the mock framework to create a mocks of all the classes involved that you don't care about.

[edited for correctness] If a method you need to test is private it may make sense to change it's scope modifier to protected if the scope modifier is unnecessarily strict. Protected access should give your tests access (because your test should be defined in the same package as the class it is testing).

If you can not change the modifier on that specific method, another option is to extract the specific code you need to test to a new method with a protected modifier, and call that new method directly from your test.

It looks like you would want a ServerConfigurationTest.java class which would test reading a very simplified Server.xml file, then verify that you have recorded the data from that file correctly.

Separately, you want a ServerServiceTest.java class. You would create a mock of whatever class ServerService uses to access the data from Server.xml (presumably ServerConfiguration). Check out the behavior page from their documentation. Modified, you would have something like:

  // create and populate testConfigServersList with test data
  expect(configMock.getActiveServers())
  .andReturn(testConfigServersList);

Because you are calling the method directly, you don't need to "start" the thread. The junit class is already going to be executed. You are just setting the state on some test objects, running the method you are testing, and then validating the state changed in the way you expected.

You would then have a second test that looks the same, but your test data has only inactive servers, then you would verify that no servers were started. EasyMock will let you verify that a method on your class was called, but not actually allow the method to run using a feature called Partial Mocking. So you would create a partial mock of ServerService and mock out the method where it actually starts another server. If ServerService has one giant method that reads the data from ServerConfiguration and starts up a new server for each active server, then you need to refactor your code and extract the new server start-up to a separate method.