PHPUnit - Testing Switch/Default cases

Hi All

I have a question about PHPUnit. I want to write a test case for the following Message class and want to cover the default: case in my test cases by passing an invalid $type in the isValidMessageType() method. Just to give you a proper scenario of when this will be useful, suppose the developer adds another type i.e. 3 in the isValidMessageType() method but forgets to add a switch case in the SendMessage() method, in that scenario the default case will throw an exception.


class Message
{

	public function isValidMessageType($type)
	{
		return ($type == 1 || $type == 2)
	}

	public function SendMessage($type)
	{

		if(!$this->isValidMessageType($type)){
			throw new Exception('Invalid Message type');
		}

		switch ($type) {
			case 1:
				// do something
				break;
			case 2:
				// do something
				break;
			default:
				throw new Exception('Invalid Message type');
		}

	}

}


Can someone please help me how to achieve this?

Thanks in advance

You need to first install PHPUnit, I assume this is done already. Next, create a new class file with a class called MessageTest that extends from PHP Unit’s base TestCase class. Finally, add two methods to this test class: testIsValidMessage() and testSendMessage(), use common testing methodology such as assertTrue() and assertEquals() with mock message objects(objects that you create for testing purposes, they may or may not have correct states). The first method should be very simple to test(2-3 assertTrue() should be enough), the second may be a bit difficult and will require some creativity(since it’s a void method that returns nothing).

Also this may not be relevant to your question, but I believe your class design is flawed to begin with. A message class whose behavior depends on type-code is a poor OO design, instead you are better off either using Inheritance/Polymorphism to create specialized message sub-classes corresponding to a single message type, or applying composite/strategy design pattern to compensate behaviors that alter depending on the message type. The problem is, assume you have another method similar to sendMessage() that depends on the type of your message, you will end up writing another switch…case statement checking exactly the same type code again. Switch…case statement itself is usually considered a bad smell in programming, duplicated switch…case statement is pretty much always a sign of improper design. I personally only use switch…case in factory classes(and in fact, using dynamic method call even factory methods can eliminate switch…case statements), and make sure the same switch condition/type is checked no more than once. Read the book Pro PHP Refactoring and you will find techniques such as Replace Typecode with State/Strategy and Replace Conditionals/Switches with Polymorphism, these are all adapted from Martin Fowler’s original book on refactoring and will help you design a better software.

The short answer is you can’t! Your if statement will throw the exception before your switch statement is ever considered. So the defafult case in your switch statement is redundant and should be removed.

Will following this approach add to code coverage for the original “Message” class?

One more question <offtopic>

Suppose I have a method GetUserDetails() in the class “User”, and there are 10 possible test cases, should I be adding all those 10 test cases in the testGetUserDetails() method in the UserTest class or do I write each cases in separate methods like testGetUserDetailsCaseA(), testGetUserDetailsCaseB(), testGetUserDetailsCaseC() etc etc??

Thanks for your reply.

Yes I know which is why I gave you a scenario in my original post that why I have to have 2 separate condition checking…

Just to give you a proper scenario of when this will be useful, suppose the developer adds another type i.e. 3 in the isValidMessageType() method but forgets to add a switch case in the SendMessage() method, in that scenario the default case will throw an exception.

Then you’d likely catch it when he tests his code to verify the message appeared. That becomes an Integration test and no longer a Unit Test.

One more question <offtopic>

Suppose I have a method GetUserDetails() in the class “User”, and there are 10 possible test cases, should I be adding all those 10 test cases in the testGetUserDetails() method in the UserTest class or do I write each cases in separate methods like testGetUserDetailsCaseA(), testGetUserDetailsCaseB(), testGetUserDetailsCaseC() etc etc??

Thanks

That is what we (the company I work for) do. Granted we name ours like so:
when_user_details_is_admin()
when_user_details_is_missing_name()
etc.