How to test a function returning single value like expected onNext actual onComplete.? - integration-testing

I am writing the test cases for one of the Spring Webflux function as:
public Mono<ClassTempKey> getKey(Param param1) {
return getKeyFromBaseClass();
}
StepVerifier.create(class.getKey(param1)
.assertNext(key -> {
assertThat(key.getValue().isEqualTo(value);
}).verifyComplete();
I am getting the following output
expected: onNext() actual: onComplete()
The method will return a single key value. Not sure where I am doing wrong.

That would be clearer if you'd post the actual code of getKeyFromBaseClass() method.
But it looks like that method returns empty Mono, without any value. In reactor empty mono without additional handling returns onComplete signal (not onNext), so you can see it in your test.

Related

An example (or several) about method at() in phpunit

Would anybody, please, show me an example for at method in phpunit test doubles. I don't understand what is its purpose?
The purpose of the at() function is to specify the order that methods on a mock should be called. If you were to use once() or exactly(), the test would pass no matter which order the methods were called as PHPUnit is only checking that they are called during the test not when.
For example:
class FooTest extends PHPUnitTestCase {
public function testProperOrderOfMethods() {
$mockObject = $this->getMockBuilder('BarObject')
->setMethods(['baz', 'boz'])
->getMock();
$mockObject->expects($this->at(0))
->method('boz');
$mockObject->expects($this->at(1))
->method('bar');
$sut = new Foo();
$sut->methodBeingTested($mockObject);
}
This requires that our function needs to look like:
public function methodBeingTested($dependecy) {
$dependency->boz();
$dependency->bar();
}
And would fail if the function order were changed.
An example use case might be your class is using an object that connects to a service and retrieves data. You would want to have the connection opened, retrieve the data, and then close the connection. Or it may need to make further requests depending on the response. Either way all of these actions need to happen in a specific order so in your test, you would use at().

Unable to get data from ajax function call from WCF service in first attempt

[WebMethod]
public static string LoadAccount()
{
address = new EndpointAddress(objClientSession.ServiceURL);
proxy = new PMToolServices.MyAppServiceClient(binding, address);
//Now call the web service to get the accounts
proxy.wsGetAccountsCompleted += new EventHandler<MyAppServices.wsGetAccountsCompletedEventArgs>(proxy_wsGetAccountsCompleted);
proxy.wsGetAccountsAsync();
return strAccountList;
}
I am calling LoadAccount WebMethod using ajax. In LoadAccount I have added callback proxy_wsGetAccountsCompleted to wsGetAccounts of WCF. In proxy_wsGetAccountsCompleted I'm building result to return to LoadAccount.
Issues:
I'm unable to return result directly from 'proxy_wsGetAccountsCompleted' so I've stored that result in global defined string and then at the end of LoadAccout WebMethod returning that. Can I return that directly from proxy_wsGetAccountsCompleted.
When I call LoadAccount WebMethod first time it returning blank result and if I call again second time then I get correct result. Even though as sequence I'm returning that global defined string after proxy_wsGetAccountsCompleted above it. Is that right?
Confused about sequence/return response between:
proxy.wsGetAccountsAsync();
proxy_wsGetAccountsCompleted();
return strAccountList
You are doing something strange: calling a wcf operation that is synchonous, that calls an asynchonous operations. Of course the first time it will not works.
LoadAccount() returns prior to get the wsGetAccountsAsync() result. You can either call wsGetAccountsAsync in synchonous way or use an asynchonous operation, like using Signal R.
Remember that when call the operation by the 2nd time, you will get result from previous request, if your method was accepting some parameter, you will store a wrong value, that is the response for your previous request.

PHPUnit and Call-time pass-by-reference

I have a unit test that I am writing and have run into an annoying problem... Let's say I have the following function I am testing:
public function functionToTest(array &$data, parameter2)
{
// perform some action on the array that is being passed in by reference
}
Now, when I attempt to call this function in my unit test, I would do something like this:
public function testMyFunction()
{
$data = array('key1' => 'val1');
$mockOfClass = $this->getMockBuilder('ClassName')
->disableOriginalConstructor()
->setMethods(array('method1', 'method2')) // My function to test is NOT in this list
->getMock();
$this->mockOfClass->functionToTest($data, true);
// Perform assertions here
}
However, I receive the following error message:
Parameter 1 to ClassName::addNewFriendsToProfile() expected to be a reference, value given
This seemed very strange to me. First of all, I'm just passing an array by reference, so it it shouldn't have a problem with this. Secondly, Why parameter 1? Doesn't it mean parameter 0? Then, I tried changing the call to the following:
$this->mockOfClass->functionToTest(&$data, true);
After making this change, it works fine. Unfortunately, it also produces the following warning:
Call-time pass-by-reference has been deprecated in /PathToFile on line xxx
I do not encounter this error when running the actual code. It only throws this error in the unit test. Also, I need to use the mock as there are methods in the class I am mocking; So I can't simply create a new instance of the class and call the method that is being tested. Is there any way I can get around this?
It turns out that PHPUnit clones each of the parameters that are being passed in (Thanks Tim Lytle for pointing me to this source: Pass by reference in a callback when mocking in PHPUnit). This is what causes the error if the array is passed in without a reference at call-time in the unit test. Luckily, the solution is simple. Instead of passing the array by reference, I pass in the array by value and return the array.
before:
public function someFunction(array &$myArray)
{
$myArray[] = 'new val';
}
after:
public function someFunction(array $myArray)
{
$myArray[] = 'new val';
return $myArray;
}

Flex Event Dispatching

I have some questions with a particular structure of a program I'm writing.
I'm using a Remote Object to make a remote call to a Rails method (using WebOrb). The problem arises in the way that I get my data back.
Basically I have a function, getConditions, in which I add an event listener to my remote call and then I make the remote call. However, what I want to do is to get that data back in getConditions so I can return it. This is a problem because I only access the event result data in the event handler. Here's some basic code describing this issue:
public function getConditions():Array
{
remoteObject.getConditions.addEventListener("result", onConditionResult);
remoteObject.getConditions();
//Here is where I want to get my event.result data back
}
public function onConditionResult(event:ResultEvent):void
{
//Here's the data that I want
event.result;
}
How can I achieve this data turn-about?
Remote calls in flex are always asynchronous so you won't be able to call getConditions() and wait there for the result. You have to use a function closure to process the results, either by means of an event handler than you declare elsewhere or a dynamic one created immediately within getConditions(), like so:
remoteObject.getConditions.addEventListener("result", function(event:ResultEvent):void {
// Run the code that you would want to when process the result.
});
remoteObject.getConditions();
The advantage of doing the above is that you would be able to "see" parameters passed to getConditions() or the result of any logic that happened before addEventListener() in the function closure. This however, takes a slight performance hit compared to declaring an explicit function (for that exact reason).
I should also add that doing so requires you to clean up after yourselves to make sure that you are not creating a new listener for every request.
you do it like this
public function getConditions():Array
{
remoteObject.getConditions.addEventListener("result", onConditionResult);
remoteObject.getConditions();
}
public function callMyExtraFunction(data:Object):void
{
//Here is where you want to get your event.result data back
}
public function onConditionResult(event:ResultEvent):void
{
//Here's the data that you want
var data:Object = event.result;
callMyExtraFunction(data);
}
You could make use of Call Responder like so :
<s:CallResponder id="getOperationsResult"/>
then use these lines to get the result from get operations
getOperationResult.token = remoteObject.getOperation();
this creates the call and returns the result stores it in getOpresult
whnever u want to access this u can call that token or getOperationResult.lastResult
Hope that helps
Chris

FlexUnit and callLater

I'm trying to use callLater with FlexUnit v0.9:
public function testCallLater():void {
Application.application.callLater( addAsync(function():void {
assertTrue(true);
}, 1000));
}
but when it runs I get this error:
ArgumentError: Error #1063: Argument count mismatch on flexunit.framework::AsyncTestHelper/handleEvent(). Expected 1, got 0.
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/callLaterDispatcher2()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8628]
at mx.core::UIComponent/callLaterDispatcher()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8568]
I'm not sure what the problem is. Is callLater incompatible with FlexUnit?
First, you should really consider migrating to FlexUnit 4.0: http://blogs.digitalprimates.net/codeSlinger/index.cfm/2009/5/3/FlexUnit-4-in-360-seconds
Second, callLater is meant to be used to delay processing until the next frame in visual classes. Your test case class is not a visual class extending UIComponent, therefore you should not try to use callLater.
Third, addAsync is use to test the results of an asynchronous operation. This is typically used in testing the results of a network request, of a file read, of a timer event, etc. That is why normally you see an "event" as a parameter in the addAsync test function (because asynchronous requests use events to process results). In your case, you're not responding to an asynchronous operation with your addAsync call, and therefore you shouldn't be looking for an event in your test function. Remove the event:Event parameter and the error will go away.
However, perhaps you can re-phrase this question to state what you're trying to accomplish? The code sample that you've indicated is not really doing anything useful. If you can be a little more specific we can help you write a better test case.
For help with using addAsync with older versions of FlexUnit, see this tutorial: http://life.neophi.com/danielr/2007/03/asynchronous_testing_with_flex.html
It looks like you are expecting an event, but not getting one. I imagine the following code would work.
public function testCallLater():void {
Application.application.callLater( addAsync(function(/*removed event declaration*/):void {
assertTrue(true);
}, 1000));
}
Just in case someone needs it, this works :
private function testCallLater():void {
Application.application.callLater(doCallLater, [ addAsync(funcUnderTest, 1000) ]);
}
private function doCallLater(testFunc:Function):void {
testFunc(null); // Dummy arg necessary because of addAsync expecting one arg
}
private function funcUnderTest(e:Object = null):void {
assertTrue(true);
}

Resources