Beginning testing - how to test NuSOAP app?

Discussion of testing theory and practice, including methodologies (such as TDD, BDD, DDD, Agile, XP) and software - anything to do with testing goes here. (Formerly "The Testing Side of Development")

Moderator: General Moderators

Post Reply
jl
Forum Commoner
Posts: 53
Joined: Tue Nov 09, 2004 12:05 am

Beginning testing - how to test NuSOAP app?

Post by jl »

I'm just beginning to see the light as far as unit testing goes and want to setup a test framework for a small application I have.

The application uses NuSOAP quite a lot to get information from a remote server. Accesses to the remote server are to a paid-for service, where it's not really going to be a good idea to send lots of test messages every time I want to test the application.

I have a class that extends NuSOAP, which receives and/or sends data via NuSOAP and communicates with the top level of the app.

How can I handle this situation for testing purposes? (E.g. is there a way to 'inject' a false NuSOAP response in to my class when the app. is in debug mode, without adding actual debug code to the production code...?)

Thanks,

jl
User avatar
sweatje
Forum Contributor
Posts: 277
Joined: Wed Jun 29, 2005 10:04 pm
Location: Iowa, USA

Post by sweatje »

You probably want to look into Mock Objects.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

Also try "Server Stub", which is a more restrictive subset of Mock Objects but has been around longer.
jl
Forum Commoner
Posts: 53
Joined: Tue Nov 09, 2004 12:05 am

Post by jl »

I understand the concept here (I think), but can't quite interpret the examples as to how you actually use this method.

In simple unit test cases it looks like it's possible to test a class without having to put any test code at all actually inside the class - you test it completely externally. Can't see how you'd do that with mock objects or server stubs (at least with code below...).

Current structure of the class I want to test is this (simplified, obviously):

Code: Select all

require_once('nusoap.php') ; 

class BusinessLogic extends SomeOtherFunctionality {

  function sendMessage($message) {
 
     $client=new soapclient() ;

     $result=$client->send($message) ;

     return $result ;

  }

  function manyFunctionsLikeThis($param1 ... ) {

      $message = < build message from $params > ;

      $result=$this->sendMessage($message) ;

      < do something with result > 

  }
}
So I'd want a stub or mock object to simulate soapclient... an example of how I'd do this would be greatly appreciated..

jl
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

Read The Mock Injection Problem. Though the section leads into a discussion of partial mocks, it is valuable reading for how to implement Mocks.
When one object uses another it is very simple to just pass a mock version in already set up with its expectations. Things are rather tricker if one object creates another and the creator is the one you want to test. This means that the created object should be mocked, but we can hardly tell our class under test to create a mock instead. The tested class doesn't even know it is running inside a test after all.
jl
Forum Commoner
Posts: 53
Joined: Tue Nov 09, 2004 12:05 am

Post by jl »

Thanks. I was thinking I was going to have to restructure the class somehow, and if I'm reading that correctly it looks like that is the only way to do it. Don't know the correct OO terminology, but making a soapclient creation function instead of declaring it inside sendMessage(), then in testing subclass the class and then over-writing the soapclient creation function with creation of a mock looks like the way to go.. ( ? )
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

Well, it doesn't have to be that complicated. Marcus Baker offers many solutions, and even though he goes on to show you partial mocks, you don't *have* to use them. For your case, I'd suggest going with the first solution:

Code: Select all

<?php
    require_once('socket.php');
    
    class Telnet {
        ...
        function &connect(&$socket, $username, $password) {
            $socket->read( ... );
            ...
        }
    }
?>
Where you pass the SOAPClient from above. After all, you don't want a new SoapClient to be instantiated every time you send a message, eh?
jl
Forum Commoner
Posts: 53
Joined: Tue Nov 09, 2004 12:05 am

Post by jl »

so initialise $client outside the class altogether?

Code: Select all

$client=new soapclient() ;

$f=new foo() ;
$f->_client=&$client ;

class foo {

       var $_client ;

       function sendMessage($message) {

            $this->_client->send($message) ;

      }

}
If that's correct it looks messy to me, as $client isn't relevant outside foo
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

If it isn't relevant outside of foo, then you may want to go the optional parameter route. The object can be optionally passed in, or you can use the message object that was instantiated during construction.

I suggest you reread the Mock object and Partial mock documentation and see what seems to work best for you. I seriously don't think that you need to instantiate a new object every sent message.
JPlush76
Forum Regular
Posts: 819
Joined: Thu Aug 01, 2002 5:42 pm
Location: Los Angeles, CA
Contact:

Post by JPlush76 »

I actually created a test suite for a web services app that I was using nusoap with.
Here is a sample of one of the classes I used in my test case. I used a mock object with simpletest so I could verify what was getting sent to nusoap and that the appropriate amount of calls were made.

Code: Select all

function testErrorMessageReturnedFromPostingData()
	{
		$send_string ='<?xml version="1.0" encoding="iso-8859-1" ?><InventoryUpdateResponse><Success>0</Success><ErrorData><Error>ItemCode GHY inventory not updated, item does not exist.</Error></ErrorData></InventoryUpdateResponse>';
		$this->nusoap->expectOnce('send', array($this->baseABSTest->getFakeXMLDataString()));
		$this->nusoap->setReturnValue('send', $send_string);
		$result = $this->invManager->sendData($this->file);
		$expected = false;
		$this->assertTrue($result === $expected, "Expected: {$expected} Received: {$result}");	
		$this->nusoap->tally();
		
		$expected_regex = "/TRANSACTION FAILED(.+)ERROR/";
		$result = $this->fileManager->readErrorLogFile();
		$this->assertWantedPattern($expected_regex, $result, "Expected Regex Pattern: {$expected_regex} Received: {$result}");	
		
	}
Post Reply