How put a Task (sfBaseTask) in unitest? - symfony1

How i can write an unit test, for my Task (sfBaseTask) ?

If you're asking how to write a unit test for a task than firstly you need to initialize configuration:
$configuration = ProjectConfiguration::hasActive() ? ProjectConfiguration::getActive() : new ProjectConfiguration(realpath($_test_dir . ‘/..’));
Later, as tasks are just classes, you can easily initialize them and test:
$task = new myTask($configuration->getEventDispatcher(), new sfFormatter());
$task->run($argumentsArray, $optionsArray);
However, I think it's better to put task logic into separate class(es) and use them in task's execute() method. It's even easier to test this way.

Related

How do we test interactor organizers using rspec?

I want to test below organizer interactor for, calling the 2 specified interactors without executing the calling interactors('SaveRecord, PushToService') code.
class Create
include Interactor::Organizer
organize SaveRecord, PushToService
end
I found few examples where the overall result of all the interactors logic(record should be saved and pushed to other service) has been tested. But, i dont want to execute the other interactor's logic as they will be tested as part of their separate specs.
1. Is it possible to do so?
2. Which way of testing(testing the overall result/testing only this particular
organizer interactor behavior) is a better practise?
I believe we need to test the interactor organizer for included interactors without executing the included interacors. I am able to find a way stub and test the organizer with below lines
To Stub:
allow(SaveRecord).to receive(:call!) { :success }
allow(PushToService).to receive(:call!) { :success }
To Test:
it { expect(interactor).to be_kind_of(Interactor::Organizer) }
it { expect(described_class.organized).to eq([SaveRecord, PushToService]) }
Found call! method & organized variable from interactor organizer source files where it is trying to call and use internally. Stubbing the call! method and testing the organized variable has fulfilled my requirement.
You can test they are called and the order:
it 'calls the interactors' do
expect(SaveRecord).to receive(:call!).ordered
expect(PushToService).to receive(:call!).ordered
described_class.call
end
See: https://relishapp.com/rspec/rspec-mocks/docs/setting-constraints/message-order
Just iterating over #prem answer.
To Test:
it { expect(interactor).to be_kind_of(Interactor::Organizer) }
it { expect(described_class.organized).to eq([SaveRecord, PushToService]) }
interactor in this case is an instance of the Interactor class, or in Rspec syntax:
let(:interactor) { described_class.new }

How do I get $resource to resolve its promise in test environment

I have a controller that needs to run several asynchronous methods that interact with the data on the client and make no calls to the server. I have one method working fine in the browser, but I want to drive the methods with tests and I can't get it to work in the test environment (Karma and Mocha). The reason is that the empty array that $resource.query() returns never gets populated in the test environment because the promise doesn't get resolved. Here is my beforeEach in the test suite.
beforeEach(inject(function($rootScope, $controller, scheduleService){
scope = $rootScope.$new();
sc = $controller('scheduleCtrl', {
$scope: scope, service: scheduleService
});
scope.$apply();
}));
scheduleCtrl has a property schedule that is assigned to the result of Resource.query() in it's constructor. I can see the three returned objects loaded into the MockHttpExpectation.
But when I go to run the test sc.schedule is an still an empty array, so the test fails. How do I get the Resource.query() to resolve in the test?
Resource.query() works with promisses, which is a assync process.
It happens that your test execute before the assynchronous request have completed and before array gets populated.
You could use $httpBackend so you can call expect after $httpBackend.flush().
Or you could retrieve the $promisse returned from Resource.query().$promisse on your test and do the expectation inside its implementation.
Ex:
$scope.promisse = Resource.query().$promisse;
sc.promisse(function(values) {
expect(values.length).not.toBe(0);
});

Grails spock database locking

I have a service method that locks a database row.
public String getNextPath() {
PathSeed.withTransaction { txn ->
def seed = PathSeed.lock(1)
def seedValue = seed.seed
seed.seed++
seed.save()
}
}
This is how my spock test looks like:
void "getNextPath should return a String"() {
when:
def path = pathGeneratorService.getNextPath()
then:
path instanceof String
}
It's just a simple initial test. However I get this error when I run the test:
java.lang.UnsupportedOperationException: Datastore [org.grails.datastore.mapping.simple.SimpleMapSession] does not support locking.
at org.grails.datastore.mapping.core.AbstractSession.lock(AbstractSession.java:603)
at org.grails.datastore.gorm.GormStaticApi.lock_closure14(GormStaticApi.groovy:343)
at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:37)
at org.grails.datastore.gorm.GormStaticApi.lock(GormStaticApi.groovy:342)
at com.synacy.PathGeneratorService.getNextPath_closure1(PathGeneratorService.groovy:10)
at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:712)
at com.synacy.PathGeneratorService$$EOapl2Cm.getNextPath(PathGeneratorService.groovy:9)
at com.synacy.PathGeneratorServiceSpec.getNextPath should return a String(PathGeneratorServiceSpec.groovy:17)
Does anyone have any idea what this is?
The simple GORM implementation for Unit tests does not support some features, such as locking. Moving your test to an integration test will use the full implementation of GORM instead of the simple implementation used by unit tests.
Typically when you find yourself using anything more than the very basic features of GORM you will need to use integration tests.
Updated 10/06/2014
In more recent versions of Grails and GORM there is now the HibernateTestMixin which allows you to test/use such features in Unit tests. Further information can be found in the documentation.
As a workaround, I was able to get it working by using Groovy metaprogramming. Applied to your example:
def setup() {
// Current spec does not test the locking feature,
// so for this test have lock call the get method
// instead.
PathSeed.metaClass.static.lock = PathSeed.&get
}

TestDataConfig.groovy not found, build-test-data plugin proceeding without config file

I am getting the following error when including in Mixin Build in unit tests:
TestDataConfig.groovy not found, build-test-data plugin proceeding without config file
it works like charm in the integration tests but not part of unit tests. I mean, 'build' plugin works itself in unit test but the 'TestDataConfig' is not populating default values
Thank You
First you should verify the version from build-test-data in your BuildConfig.groovy
test ":build-test-data:2.0.3"
Second, check your test. If you want build objects you need:
import grails.buildtestdata.mixin.Build
...
#TestFor(TestingClass)
#Build([TestingClass, SupportClass, AnotherClass])
class TestingClassTest{
#Test
void testMethod{
def tc1 = TestingClass.build()
def sc1 = SuportClass.build()
def ac1 = AnotherClass.build()
}
}
Third, check the domains constraints, you could have some properties validations like unique that fails when you build two instances. You need set that properties in code:
def tc1 = TestingClass.build(uniqueProperty: 'unique')
def tc2 = TestingClass.build(uniqueProperty: 'special')
I guess the dependency should be:
test ":build-test-data:2.0.3"
Since is just used for testing, right?

Grails Quartz Job Integration test - Not autowired Job

I'm writing the Integration test for a Quartz Job in a grails application.
I've the Job in grails-app/jobs folder, and if I start the application it works. The problem is that I want to get it in an integration test, but the autowire won't work. The test is like:
class MyJobTest{
MyJob myJob
def setUp(){
assert myJob != null
}
def testExecute(){
//test logic
}
}
but it fails because myJob is null...some help?
Quartz Jobs are not autowired like services are under the test environment. The documentation for the Quartz job also explicitly states that by default it will not execute on schedule under the test environment (you could change that if you want to but I wouldn't). I would just instantiate myJob = new MyJob() in your setUp and call the execute() method to test it. If you're trying to test the triggers you may want to find a way to look at what is inside the triggers {} maybe inspecting the metaClass?
EDIT IN RESPONSE TO COMMENT:
I've never gotten the services out of the application context so that might work. The way I would probably test it is as follows:
Assuming your class looks something like this:
class MyJob {
def myServiceA
def myServiceB
def execute() {
if(myJobLogicToDetermineWhatToDo) {
myServiceA.doStuff(parameter)
} else {
myServiceB.doStuff(parameter)
}
}
}
What you're really wanting to test here is the myJobLogicToDetermineWhatToDo. I would assume that you have (or can easily write) integration and/or unit tests against your services myServiceA and myServiceB to ensure that they are working correctly. I would then write unit tests to test the logic/wiring of your Job to the appropriate service.
#Test
void routeOne() {
def job = new MyJob()
def myServiceA = new Object()
def expectedParameter = "Name"
def wasCalled = false
myServiceA.metaClass.doStuff = {someParameter ->
assert expectedParameter == someParameter
wasCalled = true
}
job.myServiceA = myServiceA
//Setup data to cause myServiceA to be invoked
job.execute()
assert wasCalled
}
Then repeat this process for all of the routes you have through your Job. This way you can isolate your tests down to the smallest part possible and test the logic of the object that you're invoking not the services it is using. I would assume you're using a service because the logic in there is being used by another part of the system. If you're testing the service through this job and for some reason the job goes away then you have to re-write your tests to invoke the service directly. The way that I've proposed you have tests testing the service directly and tests that mock out those service calls. If the job goes away you would simply delete the tests associated with it and you won't loose any test coverage. Kinda long winded but that's how I would approach testing it.

Resources