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.
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().
How can I write the two lines of code below into one line of code:
$service_review->user_id=\Auth::user();
$user_service->service_reviews()->save($service_review);
The reason being that the line including Auth::user() is throwing an error since it's a foreign key in my "service_reviews" table and so "DOESN'T HAVE A DEFAULT VALUE"
The problem is if I give precedence to:
\Auth::user()->service_reviews()->save($service_review);
Then in this case, the authorized user is fetched but my user_service_id now throws the error as "DOESN'T HAVE A DEFAULT VALUE".
The code of my store method (This is from my ReviewsController that is based on a Nested Route:
Route::resource("services.reviews", "ReviewsController"); is as follows:
public function store(ReviewsRequest $request, $id){
$service_review = new Service_review($request->all());
$user_service = User_service::findOrFail($id);
$service_review->user_id=\Auth::user();
$user_service->service_reviews()->save($service_review);
return redirect("reviews");
I reckon passing them in one line of code will solve this error.
Yes your're right #MinaAbadir
I ended up doing it as follows:
public function store(ReviewsRequest $request, $id){
$service_review = new Service_review($request->all());
$user_service = User_service::findOrFail($id);
$service_review->user_id = \Auth::user()->email;
$user_service->service_reviews()->save($service_review);
return redirect("reviews");
}
It seems calling the specific column you want retrieved negates the foreign key problem. Maybe MySQL figures out the relationship via Eloquent. Let me know if I can clean this up further.
PHPUnit contains an assertEquals() method, but it also has an assertSame() one. At first glance it looks like they do the same thing.
What is the difference between the two? Why are they both specified?
I use both sporadically, but according to the docs:
assertSame
Reports an error identified by $message if the two variables $expected and $actual do not have the same type and value."
And as you can see in the example below the above excerpt, they are passing '2204' and 2204, which will fail using assertSame because one is a string and one is an int, basically:
'2204' !== 2204
assertSame('2204', 2204) // this test fails
assertEquals
"Reports an error identified by $message if the two variables $expected and $actual are not equal."
assertEquals does not appear to take datatype into consideration so using the above example of 2204:
'2204' == 2204
assertEquals('2204', 2204) // this test passes
I just ran some unit tests against the above examples, and indeed they resulted in documented behavior.
When it comes to objects comparison:
assertSame
Can only assert if two objects are referencing the same object instance. So even if two separate objects have for all of their attributes exactly the same values, assertSame() will fail if they don't reference the same instance.
$expected = new \stdClass();
$expected->foo = 'foo';
$expected->bar = 'bar';
$actual = new \stdClass();
$actual->foo = 'foo';
$actual->bar = 'bar';
$this->assertSame($expected, $actual); // FAILS
assertEquals
Can assert if two separate objects match their attribute values in any case. So it's the method suitable for asserting object match.
$this->assertEquals($expected, $actual); // PASSES
Reference
$this->assertEquals(3, true);
$this->assertSame(3, true);
The first one will pass!
The second one will fail.
That is the difference.
I think you should always use assertSame.
As it's been said before, assertSame reports an error if the two elements do not share type and value but it's also important to note this from the documentation:
Reports an error identified by $message if the two variables $expected
and $actual do not reference the same object.
So this test would fail too even though they share type and value:
class SameTest extends TestCase
{
public function testFailure()
{
$this->assertSame(new stdClass, new stdClass);
}
}
Moreover,
// Passes
$this->assertSame("123.", "123.");
$this->assertEquals("123.", "123");
// Fails
$this->assertSame("123.", "123");
Never use assertEquals (and family)*
* unless arguments were first manually type-checked, or you're fully aware of the behavior and are prepared for tests to pass when it treats, say, true and 42, as equal--I can't imagine why one would tolerate the risk of extremely subtle false positives in critical testing code.
For primitive values (other than floats) and arrays
Use assertSame. The behavior is predictable. "42" and true are not equal.
For floats
Avoid if possible by using integers. If you must compare floats, assertEqualsWithDelta is as broken as assertEquals:
$this->assertEqualsWithDelta(0.99, "1", 0.1); // passes :\
$this->assertEqualsWithDelta(99999, true, 0.1); // passes D:
The implementation of assertEqualsWithDelta uses an inaccurate approach, as Comparing Floating Point Numbers describes: abs($this->value - $other) < PHP_FLOAT_EPSILON;, so you might want to write a custom function.
Or type-check before calling assertEqualsWithDelta to avoid the more immediate issues:
function is_number($v) {
return is_float($v) || is_int($v);
}
class FloatTest extends TestCase {
private function assertClose(
$expected,
$actual,
$delta = 1e-7
): void {
if (!is_number($expected)) {
$type = gettype($expected);
throw new Error("\$expected type $type was not a number");
}
else if (!is_number($actual)) {
$type = gettype($actual);
throw new Error("\$actual value $type was not a number");
}
else if (!is_number($delta)) {
$type = gettype($delta);
throw new Error("\$delta value $type was not a number");
}
$this->assertEqualsWithDelta($actual, $expected, $delta);
}
public function testFloats() {
$this->assertClose(2, "2"); // fails as it should
}
}
For objects
Use a custom equals(self $other): bool function and assertObjectEquals.
If all else fails
You can't go wrong with assertTrue, the downsides being a lack of semantic appropriateness and poor default error message.
assertSame() == Tests that if the actual output and the expected parameter are same.
that is :
$this->assertSame('$expected','$expected');
or
$this->assertSame('100','100');
assertEquals == If we see with respect to a website page, i have a page which has 2 'table' so when i run assertEquals i will check its count that the 'table' are 2 by using a count function.
Eg:
$this->assertEquals(2, $var->filter('table')->count());
Here we can see that assertEquals checks that there are 2 tables found on the web page. we can also use divisions found on the page using '#division name' inside the bracket.
Eg 2:
public function testAdd()
{
$calc = new Calculator();
$result = $calc->add(30, 12);
// assert that our calculator added the numbers correctly!
$this->assertEquals(42, $result);
}
As previously mentioned, assertEquals() is primarily about an interpreted value, be it by type juggling or an object with an __magic presentation method (__toString() for example).
A good use case for assertSame() is testing a singleton factory.
class CacheFactoryTest extends TestCase
{
public function testThatCacheFactoryReturnsSingletons()
{
$this->assertSame(CacheFactory::create(), CacheFactory::create());
}
}
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);
}