CakePHP 3 integeration test without a model/entity - testing

I'm trying to test a controller function...
I want to test a couple of things:
A) That it throws an invalid request exception when a certain argument is used
B) That it works correctly when the correct argument is made.
I've written some unit tests and those all seem cool. The only documentation I can find on this is http://book.cakephp.org/3.0/en/development/testing.html but the integration testing, whilst interesting and potentially useful, I can't seem to get how I am suppose to be implement it without using fixtures (which I don't want to do necessarily).
namespace App\Test\TestCase\Controller;
use Cake\ORM\TableRegistry;
use Cake\TestSuite\IntegrationTestCase;
class MusterControllerTest extends IntegrationTestCase
{
public function testIn()
{
$this->in();
$this->setExpectedException('Invalid request');
}
}
class MusterController extends AppController {
public $helpers = array('Address');
public function beforeFilter(Event $event) {
$this->Auth->allow('in');
$this->layout = 'blank';
$this->autoRender = false;
$this->loadComponent('Rule');
parent::beforeFilter($event);
}
public function in($param = null){
if (!$this->request->is(array('post', 'put')) || $this->request->data('proc')!='yada' || is_null($param)){
throw new NotFoundException(__('Invalid request'));
}
$this->processRequest($this->request->data('hit'), $this->request->data('proc'), $param);
}
Pointers appreciated.

The IntegrationTestCase class, as its name implies, is meant for integration testing. That is, it will be testing the interaction between the controller and any other class it uses for rendering a response.
There is another way of testing controller, which is more difficult to accomplish, but allows you to test controller methods in isolation:
public function testMyControllerMethod()
{
$request = $this->getMock('Cake\Network\Request');
$response = $this->getMock('Cake\Network\Response');
$controller = new MyController($request, $response);
$controller->startupProcess();
// Add some assertions and expectations here
// For example you could assing $controller->TableName to a mock class
// Call the method you want to test
$controller->myMethod('param1', 'param2');
}

Related

How to unit test azure function using Xunit and Moq

I am very new to unit tests and recently started learning it from various online resources.
But still it confuses me when I need to implement it in my code.
For the given image which I have attached here, could anyone of you suggest me how should I start or where to start?
This is Azure function which I will be creating unit test for, framework/library I would prefer is Xunit and moq.
As mentioned in a comment, a good place to start when unit testing is looking at your code and identifying the different "paths" it can take and what the result of that path will be.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
else
{
// path 2
_logger.LogInformation("Unable to process HBSI Rate plan Queue.");
}
In your code, because of your if statement, there are 2 possible paths which will end in 2 different results = 2 unit tests.
Now you can start creating your unit tests but first you need to find out what you need to set up to be able to trigger your code.
private readonly ILogger _logger;
private readonly IInventoryService _inventoryService;
public InventoryServiceBusFunction(ILogger logger, IInventoryService inventoryService)
{
_logger = logger;
_inventoryService = inventoryService;
}
You have some dependencies being passed into your constructor with interfaces - great, this means we can mock them. We want to mock dependencies in unit tests because we want to control their behaviour for the tests. Also, mocking the dependencies negates any "real" behaviour the dependency might be performing i.e. database operations, API calls etc.
Using Moq we can mock the objects like so:
public class InventoryServiceBusFunctionTests
{
private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>();
private readonly Mock<IInventoryService> _mockInventoryService = new Mock<IInventoryService>();
...
We will use these mocks later to make verifications on behaviour we expect to happen.
Next, we need to create an instance of the actual class we want to test.
// using a constructor in the test class will run this code before each test
public InventoryServiceBusFunctionTests()
{
// pass the mocked objects to initialize class
_inventoryServiceBusFunction = new InventoryServiceBusFunction(_mockLogger.Object, _mockInventoryService.Object);
}
Now that we have an instance of the InventoryServiceBusFunction class, we can use any of the public properties/methods in our tests.
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
Now, remembering the paths from earlier, we can start to create the test cases. We can take the first path and create a [Fact] for it. You want to give your test case a meaningful name. I usually use the style of Given_When_Then to describe what is expected to happen.
Next, I usually add 3 comment sections to my test case:
// arrange
// act
// assert
This allows me to clearly see which parts of the test are doing what.
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
Next, I would fill in the \\ act section because this will tell me (via Intellisense) what I need to arrange. e.g. above, when hovering my mouse over the Run method, I can see that I need to pass an instance of InventoryRequest.
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
In the \\ arrange section, initialize an instance of the InventoryRequest class and set the properties. This can be any data as we aren't really interested in the data itself but more what happens when the code runs.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
Lastly, the \\ assert section. Here, we want to make assertions on what we expect to happen given the set up of the test. So given the InventoryRequest is not null, we expect the if to evaluate to true and we expect the _inventoryService.ProcessRequest(inventoryRequest) method to be executed.
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
In Moq, we can use the .Verify() method on the mock object to assert that the method was called. We can use the It.Is<T> syntax to make assertions on the data that is passed to the method.
Here is the full test case for path 1:
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
}
Then for path 2, you are setting up the test so that the else condition is executed.
[Fact]
public async Task GivenInventoryRequestIsNull_WhenFunctionRuns_ThenInventoryServiceDoesNotProcessRequest()
{
// arrange
InventoryRequest inventoryRequest = null;
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.IsAny<InventoryRequest>()), Times.Never);
}
Note - in the \\ assert here, I am asserting that the await _inventoryService.ProcessRequest(inventoryRequest) method is never called. This is because you want the test to fail in this scenario as the method should only be executed in the if condition. You may also choose to verify that the logger method is called with the correct message.

How to write a PHPUnit test for a SOAP server?

UPD. Sorry, guys.
I have an application that acts as a SOAP server, how do I write a PHPUnit test to test it?
SOAP extension is reading data from PHP input stream. You just provide your own data there and create some integration/unit tests for your API.
Take a look at the signature of SoapServer::handle() method. It takes as an argument a string which is a request itself. This parameter is optional and if you don't pass anything in, PHP will just read the data itself. But you can simply override it.
I used streams to do it. First you wrap the SoapServer with your own class like this:
class MyServer
{
/** \SoapServer */
private $soapServer;
public function __construct(\SoapServer $soapServer)
{
$this->soapServer = $soapServer;
}
public function handle(Psr\Http\Message\StreamInterface $inputStream): void
{
$this->soapServer->handle($inputStream->getContent());
}
}
Now you are ready to mock the request.
In your test you can do:
class MyTest extends TestCase
{
public function testMyRequest(): void
{
$mySoapServer = $this->createMySoapServer();
$request = $this->createRequest();
$mySoapServer->handle($request);
}
private function createRequest(): StreamInterface
{
$requestString = '<soap:Envelope></soap:Envelope>';
$fh = fopen('php://temp', 'rw');
fwrite($fh, $requestString);
fseek($fh, SEEK_SET);
return new Psr\Http\Message\StreamInterface\Stream($fh);
}
private function createMySoapServer(): MyServer
{
return new MyServer(new \SoapServer());
}
}
One thing to keep in mind - this test will generate output. You may want to test this output or ignore it. Depends on your use case.
Another side note. What you are asking for has really nothing to do with PHPUnit. It just a matter of designing your SOAP server correctly.
If you are wondering how to set up the stream when you have a live request, this is really simple:
$server->handle(new Psr\Http\Message\StreamInterface\Stream(fopen('php://input', 'r+')));

Understanding cakephp3 error handling

I want to create a maintenance Page for my cake website by checking a Database Table for a maintenance flag using a sub-function of my AppController "initilize()" method. If the flag is set, i throw my custom MaintenanceException(Currently containing nothing special):
class MaintenanceException extends Exception{
}
To handle it, I implemented a custom App Exception Renderer:
class AppExceptionRenderer extends ExceptionRenderer {
public function maintenance($error)
{
return "MAINTENANCE";
}
}
I am able to see this maintenance Text on my website if I set my DB flag to true, but I could not find any information in cake's error handling documentation (http://book.cakephp.org/3.0/en/development/errors.html) on how I can actually tell the Exception renderer to render view "maintenance" with Template "infopage".
Can I even us that function using the ExceptionRenderer without a custom error controller? And If not, how should a proper ErrorController implementation look like? I already tried this:
class AppExceptionRenderer extends ExceptionRenderer {
protected function _getController(){
return new ErrorController();
}
public function maintenance($error)
{
return $this->_getController()->maintenanceAction();
}
}
together with:
class ErrorController extends Controller {
public function __construct($request = null, $response = null) {
parent::__construct($request, $response);
if (count(Router::extensions()) &&
!isset($this->RequestHandler)
) {
$this->loadComponent('RequestHandler');
}
$eventManager = $this->eventManager();
if (isset($this->Auth)) {
$eventManager->detach($this->Auth);
}
if (isset($this->Security)) {
$eventManager->detach($this->Security);
}
$this->viewPath = 'Error';
}
public function maintenanceAction(){
return $this->render('maintenance','infopage');
}
}
But this only throws NullPointerExceptions and a fatal error. I am really dissapointed by the cake manual as well, because the code examples there are nowhere close to give me an impression of how anything could be done and what functionality I actually have.
Because I had some more time today, I spent an hour digging into the cake Source and found a solution that works well for me (and is propably the way it should be done, altough the cake documentation does not really give a hint):
Step 1: Override the _template(...)-Method of the ExceptionRenderer in your own class. In my case, I copied the Method of the parent and added the following Code at the beginning of the method:
$isMaintenanceException = $exception instanceof MaintenanceException;
if($isMaintenanceException){
$template = 'maintenance';
return $this->template = $template;
}
This tells our Renderer, that the error Template called "maintentance"(which should be located in Folder: /Error) is the Error Page content it should render.
Step 2: The only thing we have to do now (And its is kinda hacky in my opinion, but proposed by the cake documentation in this exact way) is to set the layout param in our template to the name of the base layout we want to render with. So just add the following code on top of your error template:
$this->layout = "infopage";
The error controller I created is actually not even needed with this approach, and I still don't know how the cake error controller actually works. maybe I will dig into this if I have more time, but for the moment.

Automatic object cache proxy with PHP

Here is a question on the Caching Proxy design pattern.
Is it possible to create with PHP a dynamic Proxy Caching implementation for automatically adding cache behaviour to any object?
Here is an example
class User
{
public function load($login)
{
// Load user from db
}
public function getBillingRecords()
{
// a very heavy request
}
public function computeStatistics()
{
// a very heavy computing
}
}
class Report
{
protected $_user = null;
public function __construct(User $user)
{
$this->_user = $user;
}
public function generate()
{
$billing = $this->_user->getBillingRecords();
$stats = $this->_user->computeStatistics();
/*
...
Some rendering, and additionnal processing code
...
*/
}
}
you will notice that report will use some heavy loaded methods from User.
Now I want to add a cache system.
Instead of designing a classic caching system, I just wonder if it is possible to implement a caching system in a proxy design pattern with this kind of usage:
<?php
$cache = new Cache(new Memcache(...));
// This line will create an object User (or from a child class of User ex: UserProxy)
// each call to a method specified in 3rd argument will use the configured cache system in 2
$user = ProxyCache::create("User", $cache, array('getBillingRecords', 'computeStatistics'));
$user->load('johndoe');
// user is an instance of User (or a child class) so the contract is respected
$report = new report($user)
$report->generate(); // long execution time
$report->generate(); // quick execution time (using cache)
$report->generate(); // quick execution time (using cache)
each call to a proxyfied method will run something like:
<?php
$key = $this->_getCacheKey();
if ($this->_cache->exists($key) == false)
{
$records = $this->_originalObject->getBillingRecords();
$this->_cache->save($key, $records);
}
return $this->_cache->get($key);
Do you think it is something we could do with PHP? do you know if it is a standard pattern? How would you implement it?
It would require to
implement dynamically a new child class of the original object
replace the specified original methods with the cached one
instanciate a new kind of this object
I think PHPUnit does something like this with the Mock system...
You can use the decorator pattern with delegation and create a cache decorator that accepts any object then delegates all calls after it runs it through the cache.
Does that make sense?

Can you use RequestFactory's .with() method with named queries?

I'm trying to make a call to a database using RequestFactory with Hibernate/JPA, and I want to retrieve a list of entities with embedded entities returned as well. I know that the .with() method works for methods like .find(), but it doesn't seem to work with custom queries.
The current way I'm doing it is as follows:
I used a named query in the entity class for the query. (Primary Entity is Name, embedded entity is a Suffix entity called nameSuffix)
#NamedQueries({ #NamedQuery(name = "Query.name", query = "select * from NameTable") })
Then in the service class, the .list() method, which is what I'd like to call with RequestFactory, is as follows.
public List<Name> list() {
return emp.get().createNamedQuery("Query.name").getResultList();
}
Finally, this is how I make the call in my client side code:
NameRequest context = requestFactory.createNameRequest();
context.list().with("nameSuffix").fire(new Receiver<List<NameProxy>>(){
public void onSuccess(List<NameProxy> response) {
String suff = response.get(0).getNameSuffix().getText();
}
});
In the above code, it says that getNameSuffix() returns null, which would imply that .with("nameSuffix") does not work with the .list() call like it does with the standard .find() method.
Is there a way to build a call that would return a list of entities and their embedded entities using .with(), or do I need to do it another way? If I need to do it another way, has anyone figured out a good way of doing it?
I think you misunderstood what the method with() is thought for, unless you had a method getNameSuffix which returns the NameSuffixentity. This is what the documentation says about it:
When querying the server, RequestFactory does not automatically populate relations in the object graph. To do this, use the with() method on a request and specify the related property name as a String
So, what you have to pass to the method is a list of the name of the child entities you want to retrieve. I hope this example could be helpful:
class A {
String getS(){return "s-a"}
B getB(){return new B();}
}
class B {
String getS(){return "s-b";}
C getC(){return new C();}
}
class C {
String getS(){return "s-c";}
}
context.getA().fire(new Receiver<A>(){
public void onSuccess(A response) {
// return 's-a'
response.getS();
// trhows a NPE
response.getB().getS();
}
});
context.getA().with("b").fire(new Receiver<A>(){
public void onSuccess(A response) {
// return 's-a'
response.getS();
// return 's-b'
response.getB().getS();
// trhows a NPE
response.getB().getC().getS();
}
});
context.getA().with("b.c").fire(new Receiver<A>(){
public void onSuccess(A response) {
// return 's-a'
response.getS();
// return 's-b'
response.getB().getS();
// return 's-c'
response.getB().getC().getS();
}
});