I don't know how to define a callback that doesn't need any parameter. In order to describe the question, let me make up a setup - mine is different but contains several more classes, harder to digest.
Lets say we have
public class CustomerA {
public Payment payWithCash() {...}
}
and
public class CustomerB {
public Payment payWithCreditCard() {...}
}
and in addition
public abstract class Factory {
public Callback<Void, Payment> getPaymentCallback();
// Some other methods
...
}
then here comes the problem: I'd like to implement something like this
public class CashFactoryA extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return CustomerA::payWithCash;
}
}
and in a different class
public class CashFactoryB extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return CustomerB::payWithCreditCard;
}
}
What happens is, that the compiler complains, that CustomerB does not define payWithCreditCard(Void) and CustomerA likewise fails for payWithCash(Void).
So how to state this correct that there is no parameter to the Callback?
I am aware that I could probably solve my problem as well with interfaces, but I like to understand how to solve this with a Callback.
Thank you in advance!
Consider making Factory generic:
public abstract class Factory<T> {
public Callback<T, Payment> getPaymentCallback();
// Some other methods
...
}
And then you can do
public class CashFactoryA extends Factory<CustomerA> {
public Callback<CustomerA, Payment> getPaymentCallback() {
return CustomerA::payWithCash;
}
}
and
public class CashFactoryB extends Factory<CustomerB> {
public Callback<CustomerB, Payment> getPaymentCallback() {
return CustomerB::payWithCreditCard;
}
}
EDIT:
This answer is a wrong approach.
First, you are trying to refer payWithCash from not a instance of CustomerA but the class CustomerA, so payWithCash must be static method.
public class CustomerA {
public static Payment payWithCash() {...}
}
Then use lambda expression which is the same interface as your Callback.
public class CashFactoryA extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return param -> CustomerA.payWithCash();
}
}
The code above has the same meaning as the code below. The param argument will be ignored as a result.
public class CashFactoryA extends Factory {
public Callback<Void, Payment> getPaymentCallback() {
return new Callback<Void, Payment>(){
#Override
public Payment call(Void param) {
return CustomerA.payWithCash();
}
};
}
}
Related
I'm writing tests against the following class:
abstract class EmailMessageRecipient
{
private $_address = null;
public function setAddress($address)
{
$this->_address = $address;
return $this;
}
public function getAddress()
{
return $this->_address;
}
}
The test looks like this:
class EmailMessageRecipientTest extends PHPUnit_Framework_TestCase
{
private $_test_object;
protected function makeTestObject()
{
return $this->createMock(EmailMessageRecipient::class);
}
public function setUp()
{
$this->_test_object = $this->makeTestObject();
}
public function testAddress()
{
$this->_test_object->setAddress('blah#example.com');
$this->assertEquals('blah#example.com', $this->_test_object->getAddress());
}
}
PHPUnit fails the test with the message Failed asserting that null matches expected 'blah#example.com'.. So $this->_test_object->getAddress() is returning null instead of the email address that was passed to it. Why is this happening and how do I adjust the test so that it passes.
Mocking the setAddress() and getAddress() methods is not an acceptable answer. The purpose of this test is to cover setAddress() and getAddress().
If you test an abstract class you should use: getMockForAbstractClass:
The getMockForAbstractClass() method returns a mock object for an
abstract class. All abstract methods of the given abstract class are
mocked. This allows for testing the concrete methods of an abstract
class.
Example 9.19: Testing the concrete methods of an abstract class
<?php
use PHPUnit\Framework\TestCase;
abstract class AbstractClass
{
public function concreteMethod()
{
return $this->abstractMethod();
}
public abstract function abstractMethod();
}
class AbstractClassTest extends TestCase
{
public function testConcreteMethod()
{
$stub = $this->getMockForAbstractClass(AbstractClass::class);
$stub->expects($this->any())
->method('abstractMethod')
->will($this->returnValue(true));
$this->assertTrue($stub->concreteMethod());
}
}
?>
I have an abstract class that has common methods in it, that I wish to test, so I do not have to keep testing them in each class that extends this class.
abstract class Class1 implements iClass1
{
const VALUE = 'A';
private $Return;
public function __construct($Field = NULL)
{
if( ! is_null($Field) )
$this->SetField($Field);
}
public function GetField()
{
return $this->Return;
}
public function SetField($Field)
{
if (strlen($Field) != 3)
throw new CLASS1_EXCEPTION('Field "' . $Field . '" must be 3 digits.');
$this->Return = $FieldCode;
}
abstract function CalculateData();
}
I want to create the basic test case then that will test the constructor, and the GetField and other functions, then my other test files can test the abstract functions.
I want to be able to test the const has not changed, the field throws the exception etc...
TEST:
class TEST_CLASS1 extends PHPUnit_Framework_TestCase
{
protected function setUp()
{
require_once('CLASS1.php');
}
public function testConstants()
{
$this->assertEquals(CLASS1, 'A');
}
/* #expectedException CLASS1_EXCEPTION
public function testLargeFieldException()
{
$class1 = new CLASS1('ABCD');
$class1 = new CLASS1();
$class1->SetField('ABCD');
}
}
How do I create the tests since I can not create the CLASS1 object as it is an abstract class?
One option is to create a
TestableClass1 extends Class1 {
public function CalculateData() {}
}
and use that class for your tests.
The other option is to do pretty much the same but use an API phpunit provides you with:
For this see the sample Example 10.13: Testing the concrete methods of an abstract class of the phpunit documentation:
A simpler example:
abstract class AbstractClass
{
public function concreteMethod()
{
return 5;
}
public abstract function abstractMethod();
}
class AbstractClassTest extends PHPUnit_Framework_TestCase
{
public function testConcreteMethod()
{
$sut = $this->getMockForAbstractClass('AbstractClass');
$this->assertSame(5, $sut->concreteMethod());
}
}
According to Cairngorm architecture, we always have a fault handler in every command class for each service.
How we can create a single Class for handling Fault handler event for all the services.
By "always having a fault handler", do you mean by contract, as in in implementing an interface?
You can write a base command class that all of your other command classes extend. The base can implement the on fault handler and all other sub-classes can optionally override it.
public class BaseCommand implements ICommand
{
public function execute( event:Event ):void
{
}
public function onFault( event:Event ):void
{
}
}
// -- no need to implement onFault in sub-class
public class MyCommand extends BaseCommand
{
public function execute( event:Event ):void
{
}
}
Create a base class that you extend all other classes from, put the fault handler there. Such as:
FaultHandlerCairngormCommand extends SequenceCommand implements IResponder
[BaseCommand.as]
public class BaseCommand extends SequenceCommand implements IResponder
{
public function execute( event:CairngormEvent ):void
{
super.execute(event);
}
public function fault( info:Object ):void
{
throw new Error("Generic request failure"); //or handle as you please
}
public function result(data:Object):void
{
throw new Error("The result method implementation defined in IResponder for all extensions of BaseCommand must be overrriden in any sub-class");
}
}
[MyCommand.as]
// -- no need to implement onFault in sub-class
public class MyCommand extends BaseCommand
{
public function execute( event:Event ):void
{
remoteObjectDelegate.doYourServerOperation(this);
}
override public function result(data:Object):void
{
trace("happily handling the data"); //without this override an error will be thrown so the developer will know to correct
}
}
I have problem with Abstract Factory pattern implementation on Spring. I am using Spring 3 MVC and Hibernate 3, which works fine if I don't use Abstract Factory Method pattern.
I am not sure what I have to add to the Controller to have access the Factory Class (CategoryFactory).
Is there anything missing in the Controller or bean initiating ?
class SectionsController extends MultiActionController {
/* Do I have to initiate the CategoryFactory here? */
public ModelAndView secList() throws Exception {
CategoryFactory.CategoryType type = CategoryFactory.CategoryType.valueOf("view");
modelMap.addAttribute("sectionList", CategoryFactory.findCategory(type).list(id));
return new ModelAndView("Form", modelMap);
}
}
Abstract Factory
public abstract class Category {
public abstract List list(int departId);
}
public class CategoryFactory {
public enum CategoryType { firstclass, secondClass, ... }
public static Category findCategory(CategoryType categoryType) {
// Create type specific Category implementation
}
}
It shoud be:
class SectionsController extends MultiActionController {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public ModelAndView secList() throws Exception {
CategoryFactory.CategoryType type=CategoryFactory.CategoryType.valueOf("view");
modelMap.addAttribute("sectionList",CategoryFactory.findCategory(type).list(hibernateTemplate,id);
return new ModelAndView("Form", modelMap);
}
}
in my implementation, I have an interface as: ICachingManager. I've got now one implementation. I also created a manager class as:
public class CachingManager
{
#region Members
private ICachingManager service;
#endregion
#region Constructors
public CachingManager(ICachingManager service)
{
this.service = service;
}
#endregion
#region Public Methods
public void EnCache<T>(string key, T value)
{
this.service.EnCache<T>(key, value);
}
public T DeCache<T>(string key)
{
return this.service.DeCache<T>(key);
}
#endregion
}
In case I had one implementation, then I can easily register the CachingManager class with Unity, automatically Unity resolves and injects the ICachingManager.
In case I had more than one implementation using named types, then how can I can make use of Unity? Do I need to make use of an Abstract Factory to decide on which named type to initialize?
Is it a good idea to make use of such a composite class or use directly implementations of the interface with Abstract Factory?
You don't have to create an abstract factory. You can inject a given named implementation:
public class MyClient
{
[Dependency("NamedManager")]
public ICachingManager CachingManager { get; set; }
// or in the constructor
public MyClient([Dependency("NamedManager")] ICachingManager cachingManager) {
// ...
}
}
or you can configure the container to do the same thing:
public class MyClient
{
public MyClient(ICachingManager cachingManager) {
// ...
}
}
...
void ContainerBuilder() {
...
Container.RegisterType<MyClient>(
new InjectionConstructor(
new ResolvedParameter<ICachingManager>("NamedManager")));
...
}