I'm somewhat new to unit testing. One thing (for now) about proper testing confuses me.
For instance, how do you test a main method if it has no state and only console output? Like this, where myServer methods & state are private?
public static void main(String[] args)
{
Server myServer = new Server()
if(myServer.start())
System.out.println("started");
else
System.out.println("failed");
}
I don't want to have to change my code and expose my Server methods & state to make them public.
Note, I'm not asking how to test myServer.start(), I'm asking how to test main() itself.
Please let me know.
Thanks guys, jbu
Q 10 - Which of the following is correct about a Unit Test Case? A - A Unit Test Case is a part of code which ensures that the another part of code (method) works as expected.
Avoid Test Interdependence You, therefore, cannot count on the test suite or the class that you're testing to maintain state in between tests. But that won't always make itself obvious to you. If you have two tests, for instance, the test runner may happen to execute them in the same order each time.
Main methods are supposed to be very thin and just get the ball rolling. Hence generally not tested. e.g. a .net Winforms app Main method may contain
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainWindow());
}
If your main method is doing a lot of stuff, consider extracting a method (to a new class if need be). e.g. as shown below... (don't have a JavaIDE handy.. the foll .net code should be easy to translate)
static void Main()
{
new MainApp().Run();
}
Now if Run can be tested.. Main too is covered. Lets look at MainApp. Refactored the 2 tasks of starting the server and logging the result as 2 methods.
public class MainApp
{
private Server m_Server;
public MainApp():this(new Server())
{}
public MainApp(Server s)
{ m_Server = s; }
public void Run()
{ Log(LaunchServer()); }
private string LaunchServer()
{ return (m_Server.start() ? "started" : "failed"); }
protected virtual void Log(string sMessage)
{ System.Console.WriteLine(sMessage); }
}
Now lets look at the test code... I'll use the "subclass and override" trick to cache the result as shown below. (You could also use Mocks.. as per taste)
public class FakeApp : MainApp
{
private string sLastLoggedMessage;
public FakeApp(Server s) : base(s) { }
public string getLastLoggedMessage()
{ return sLastLoggedMessage; }
protected override void Log(string sMessage)
{ sLastLoggedMessage = sMessage; }
}
the test is now trivial
[TestFixture]
public class TestMainApp
{
[Test]
public void TestRun()
{
Server s = new Server();
FakeApp f = new FakeApp(s);
f.Run();
Assert.AreEqual("started", f.getLastLoggedMessage());
}
}
if you can't force Server.start() to succeed or fail as per your desire.. You can create a FakeServer.. subclass and override start() to return fixed values.
If a method does something, it can be tested. If it does not, it should cease to exist. Refactor it away. HTH
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With