iOS unit testing with Core Data - unit-testing

I'm writing some tests to exercise a CoreData object: coreobj
in my test case setup method I have the following initialization:
- (void)setUp
{
[super setUp];
NSManagedObjectModel *mom = [NSManagedObjectModel mergedModelFromBundles:[NSBundle allBundles]];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
STAssertTrue([psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:NULL] ? YES : NO, #"Should be able to add in-memory store");
m_managedObjectContext = [[NSManagedObjectContext alloc] init];
m_managedObjectContext.persistentStoreCoordinator = psc;
}
My first test runs fun, but my second test generates this error in the log file:
Can't merge models with two different entities named 'coreobj'
Suggestions?

You can have a look at Blog post with grate explanation
It does not solve all the problems do ...

Setup will execute between each test case. It maybe your getting multiple contexts entities that are causing test pollution between each test.

Related

Is a Cache mock called more than once when browser-testing?

I'm trying to cover the following:
I'm using the following test code:
public function test_it_deletes_a_patient()
{
// ...
$cacheKey = vsprintf('%s.%s', [$this->doctorUser->id, 'backoffice.stats.patientsTotalCount']);
Cache::shouldReceive('has')->with($cacheKey)->once()->andReturn(false);
Cache::shouldReceive('increment')->with($cacheKey, -1)->once()->andReturn(true);
$response = $this->json('DELETE', route('patients.destroy', $this->patient), ['confirmation' => 'ELIMINAR']);
// ...
}
That triggers the following controller code:
public function destroy(Patient $patient, Request $request)
{
$this->authorize('delete', $patient);
$confirmation = $request->get('confirmation');
if ($confirmation != 'ELIMINAR') {
return response()->json(['success' => false]);
}
logger()->info("Deleting Patient Profile PATIENT_ID:[{$patient->id}]");
$patient->delete();
$this->updatePatientsCount(-1);
return response()->json(['success' => true]);
}
protected function updatePatientsCount($amount = 1)
{
$key = vsprintf('%s.%s', [auth()->user()->id, 'backoffice.stats.patientsTotalCount']);
if (Cache::has($key)) { // I want to mock for testing this
Cache::increment($key, $amount); // I want to mock for testing this
}
}
After test run I get:
alariva#trinsic:~/fimedi$ t --filter=test_it_deletes_a_patient
PHPUnit 7.3.1 by Sebastian Bergmann and contributors.
F 1 / 1 (100%)
Time: 6.53 seconds, Memory: 26.00MB
There was 1 failure:
1) Tests\Browser\Backoffice\PatientsTest::test_it_deletes_a_patient
Unable to find JSON fragment
["success":true]
within
[{"exception":"Mockery\\Exception\\NoMatchingExpectationException","file":"\/home\/alariva\/fimedi\/vendor\/mockery\/mockery\/library\/Mockery\/ExpectationDirector.php","line":92,"message":"No matching handler found for Mockery_0_Illuminate_Cache_CacheManager::has('2056e535e689ab723b3f44831b488f05f7fb8b90'). Either the method was unexpected or its arguments matched no expected argument list for this method\n\n","trace":[{"class":"App\\Http\\Middleware\\Language","file":"\/home\/alariva\/fimedi\/vendor\/laravel\/framework\/src\/Illuminate\/Pipeline\/Pipeline.php","function":"handle","line":151,"type":"->"},{"class":"Barryvdh\\Debugbar\\Middleware\\InjectDebugbar","file":"\/home\/alariva\/fimedi\/vendor\/laravel\/framework\/src\/Illuminate\/Pipeline\/Pipeline.php","function":"handle","line":151,"type":"->"},{"class":"Illuminate\\Auth\\Middleware\\Authenticate","file":"\/home\/alariva\/fimedi\/vendor\/laravel\/framework\/src\/Illuminate\/Pipeline\/Pipeline.php","function":"handle","line":151,"type":"->"},{"class":"Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse","file":"\/home\/alariva\/fimedi\/vendor\/laravel\/framework\/src\/Illuminate\/Pipeline\/Pipeline.php","function":"handle","line":151,"type":"->"},{"class":"Illuminate\\Cookie\\Middleware\\EncryptCookies","file":"\/home\/alariva\/fimedi\/vendor\/laravel\/framework\/src\/Illuminate\/Pipeline\/Pipeline.php","function":"handle","line":151,"type":"->"},{"class":"Il
What I interpret after a couple of tests, is that it looks like once I mock Cache it is being called by some middlewares before reaching the tested block, so since those called methods are not mocked, the test fails because it does not know what to answer for those middleware calls.
Imagine I could successfully mock all the calls before getting to the tested codeblock, I would be able to make it reach. But that's not the way to go over it.
How can I mock Cache and avoid failure due to previous Cache calls that I'm not testing?
EDIT: I realized after getting to a solution that this is a misleading question. My actual need was:
How can I successfully cover those lines?
Sidenote: if I try to disable middlewares ($this->withoutMiddleware();) I get an AccessDeniedHttpException
alariva#trinsic:~/fimedi$ t --filter=test_it_deletes_a_patient
PHPUnit 7.3.1 by Sebastian Bergmann and contributors.
F 1 / 1 (100%)
Time: 12.95 seconds, Memory: 24.00MB
There was 1 failure:
1) Tests\Browser\Backoffice\PatientsTest::test_it_deletes_a_patient
Unable to find JSON fragment
["success":true]
within
[{"exception":"Symfony\\Component\\HttpKernel\\Exception\\AccessDeniedHttpException","file":"\/home\/alariva\/fimedi\/vendor\/laravel\/framework\/src\/Illuminate\/Foundation\/Exceptions\/Handler.php","line":201,"message":"This action is unauthorized.","trace":[{"class":"App\\Exceptions\\Handler","file":"\/home\/alariva\/fimedi\/vendor\/laravel\/framework\/src\/Illuminate\/Routing\/Pipeline.php","function":"render","line":83,"type":"->"},{"class":"Illuminate\\Foundation\\Exceptions\\Handler","file":"\/home\/alariva\/fimedi\/app\/Exceptions\/Handler.php","function":"render","line":65,"type":"->"},{"class":"Illuminate\\Foundation\\Exceptions\\Handler","file":
Maybe I can cherry-pick middlewares to disable?
I managed to cover the controller's method by encapsulating the custom Cache operation into a macro, so as to get the benefits of spliting into code units.
I moved my code into a macro (in the boot() of a service provider):
Cache::macro('incrementExisting', function($key, $amount) {
if (Cache::has($key)) {
Cache::increment($key, $amount);
}
return $this;
});
I refactored to use the macro
protected function updatePatientsCount($amount = 1)
{
$key = vsprintf('%s.%s', [auth()->user()->id, 'backoffice.stats.patientsTotalCount']);
Cache::incrementExisting($key, $amount);
}
I could get the desired coverage while I can still test the refactored code with unit testing.
Update I
Regarding the concern of handling many calls that are not mocked, I just learned from Adam Wathan that there exists shouldIgnoreMissing() and that would allow to use the Mocking approach for this case.
Update II
Write your tests first. When doing so it gets easier to avoid hard-to-test code.

how to unit test sorting on a table from sapui5

I have this table (m.Table) in my ui5 application that I'm sorting using the following example.
https://sapui5.hana.ondemand.com/1.42.7/explored.html#/sample/sap.m.sample.TableViewSettingsDialog/preview
I have a set of unit test (QUnit) where I test this functionality but I keep getting an error saying that "Object doesn't support method sort".
This is a snippet of my code
var oBinding = controls.searchResultsTable.getBinding("items");
var aSorter = [];
var sPath = "columnName";
aSorter.push(new Sorter(sPath, false));//sort in descending order
oBinding.sort(aSorter);
This code above takes care of the sorting when the application runs and everything works fine.
Here is a snippet of my testing
QUnit.test("valid search input", function(assert){
....
//my attempt at testing this
var getBinding = sinon.stub().returns(new sap.ui.model.Binding(),
function(){});
}
var oBinding = {getBinding: getBinding};
....
The error points to the line where I do aBinding.sort(aSorter);
Looking at the api, the sap.ui.model.Binding doesn't have any "sort()" functions. So I'm not sure how the sorting even works, let alone test it. Could someone give me some guidance here?
because sort is done on sap.ui.model.ListBinding as you are doing a binding on table items. Link
Also there are different other Bindings which extends sap.ui.model.Binding like sap.ui.model.PropertyBinding(binding on single UI control), sap.ui.model.TreeBinding(binding on Tree control) and so on.

PagedResultList Instance in Grails 3.1.7 Unit Test

Is it possible to create PagedResultList instance or Mock?
For Background: Currently I´m writing Controller Unit tests. If it is necessary I stubbing Service function calls. But some of this functions have PagedResultList as return type. So i have to inject a PagedResultList instance or null.
In some cases I need an instance because the controller do something like this:
testFunction(){
def result = sampleService.doSomething()
if (result.empty) {
variable = "it´s empty"
}
render variable
}
My Test looking like this:
void "sample Test"(){
given:
controller.sampleService = Mock(SampleService)
PagedResultList emptyPagedResultList = ?????
when:
controller.testFunction()
then:
1 * controller.sampleService.doSomething() >> emptyPagedResultList
response.text == "it´s empty"
}
Someone can help me to replace the ????? with a pice of code to fix this issue?
Thanks in advance.
Yes, there are a couple options here:
You could use a real PagedResultList as the emptyPagedResultList - See FooControllerSpec.groovy line 11 for an example
You could use another Spock Mock() as the emptyPagedResultList - See FooControllerSpec.groovy line 25 for an example

Grails : Spock : Unit testing GORM domain class hooks

Usually I was ending up writing test cases for a Domain by writing them for constraints and any custom methods(created by us in application) as we know we shouldn't test obvious.
But the time we started using coverage plugin, we found that our domains line of code is not fully covered which was due to gorm hooks(onInsert, beforeUpdate) that we never wrote test cases for.
Is there a way we can test these. One possible way that seems obvious but not suitable is to call another method(containing all code which was earlier in hooks) within these hooks and test that method only and be carefree for hooks.
Any solutions...
Edit
Sample code in domain that I want to unit-test:
class TestDomain{
String activationDate
def beforeInsert() {
this.activationDate = (this.activationDate) ?: new Date()//first login date would come here though
encodePassword()
}
}
How can I unit-test beforeInsert or I would end up writing integration test case?
Perhaps a unit test like:
import grails.test.mixin.TestFor
#TestFor(TestDomain)
class TestDomainSpec extends Specification {
def "test beforeSave"() {
given:
mockForConstraintsTests(TestDomain)
when:
def testDomain = new TestDomain().save(flush:true)
then:
testDomain.activationDate != null
}
}

Bizzarre behaviour on Kiwi BDD Mock

I'm using Kiwi to test some classes and I need to stub a class method just to return a fake file path.
I know that i can solve exposing some path property or create a subclass just for test, but i prefere to keep only one class and stub some methods.
this is the test:
it(#"return the full list of POS", ^(){
NSString *sample_data_path = [[NSBundle bundleForClass:[self class]] pathForResource:#"sample_pos" ofType:#"plist"];
Class p = [PointOfSale class];
[p stub:#selector(sampleDataPath) andReturn:sample_data_path];
NSArray *allPos = [p findAll];
[[theValue([allPos count]) should] equal:theValue(100)];
});
I'm confused because this test pass and fail alternatively, one success and one failure.
There is not any "before_each"or other running test...
someone has the same issue?
I found the cause of this issue.
The method sampleDataPath in the original and in the stub class return a file path that is supposed to be in different bundle (mainbundle and test bundle).
But even the "production" file was copied in the test bundle, so we had two file with the same name on the same bundle, because of this the result of the test was unpredictable ;)
So....if you have an issue like this,double check your file names!