Spock Testing when method under test contains closure - unit-testing

I'm using grails plugin multi-tenant-single-db. Within that context I need to write a spock test in which we temporarily remove the tenant restrictions. Location is my Tenant, so my method looks like this:
def loadOjectDetails(){
Location.withoutTenantRestriction{
// code here to retrieve specific items to the object to be loaded
render( template: "_loadDetails", model:[ ... ]
}
}
The method runs as expected, but trying to put method under test coverage the error output suggests that:
groovy.lang.MissingMethodException: No signature of method: com.myPackage.myController.Location.withoutTenantRestriction() is applicable for argument types:
and a stacktrace that stems on from there.
Do I need to Stub this? The withoutTenantRestriction is a wrapper around my entire method logic.
UPDATE:
The test code looks like this:
given:
params.id = 3002
currentUser = Mock(User)
criteriaSetup()
controller.getSalesOrder >> salesOrders[2]
when:
controller.loadOrderManageDetails()
then:
(1.._) controller.springSecurityService.getCurrentUser() >> currentUser
expect:
view == 'orderMange/orderManageDetail'
model.orderInstance == salesOrders[2]

Yes! You should be stubbing it as is created at run time not compile time.
You could stub it like below:
Your_Domain.metaClass.withoutTenantRestriction{Closure closure ->
closure.call()
}
This way your regular code will work in test cases. Also,as in withoutTenantRestriction it basically starts a new hibernate session, which doesn't matter much as now you have stubbed the closure, you could perform desired action in place of calling closure.call() only.
Also, same could be applied to withThisTenant.
In integration tests you don't need to stub it as is loading the whole environment.
Hope it helps!!

Related

Sinon stub instance method declared in mapDispatchToProps

New to testing and React Redux, so I may be conflating a few issues here. I will only present one example, but I have tried many different combinations of mount(), shallow(), instance(), stub, spy and more.
Given a component, where setFooData() updates redux state and Foo.props.data:
const mapDispatchToProps = (dispatch, props) => ({
setFooData(fooId, data) {
dispatch(Actions.setFooData(fooId, data));
},
});
...
return (
<div fooId={this.props.fooId}>
<Foo {...fooProps}/>
</div>
);
I would like to write some tests around the conditions under which setFooData() is called, namely conditions in lifecycle methods like componentDidMount() and componentWillReceiveProps().
Because setFooData() involves server calls and more, and because these tests merely concern the view layer and how the component renders as a result of Foo.props.data being set eventually by setFooData(), setFooData() seems like a good candidate for stub.
Therefore, Enzyme's shallow(), rather than mount(), seems appropriate, correct? In any case, when I try to stub setFooData():
let wrapper = return shallow(<Foo {...props}/>);
let stub = sinon.stub(wrapper.instance(), 'setFooData');
I receive the error:
Attempted to wrap undefined property setFooData as function
Upon inspection, wrapper.instance() yields an object where setFooData() is indeed not defined, but according to other examples, I would think it should be.
Furthermore, setFooData() does exist on wrapper.instance().selector.props, and while let stub = sinon.stub(wrapper.instance().selector.props, 'setFooData'); avoids the error, when I inspect the object setFooData() =/= stub, and the function is not called as per the test.
When I use mount() instead,
let wrapper = mount(<Provider store={store}><Foo {...props}/></Provider>);
let componentDidMountSpy = sinon.spy(Foo.prototype, 'componentDidMount');
let componentWillReceivePropsSpy = sinon.spy(Foo.prototype, 'componentWillReceiveProps');
expect(componentDidMountSpy.called).to.be.true; //passes
expect(componentWillReceivePropsSpy.called).to.be.true; //passes
expect(stub.called).to.be.true; //fails
I receive a different error that appears related to the body of setFooData(), so setFooData() is called but the function is not actually stubbed to prevent its real body from being executed.
Thanks for any help to clarify my understanding.
I think you're taking the hardest path. You should test your component in isolation, not the connected one. If you test the connected component you're making an integration test and double testing that connect indeed works. That's already tested in react-redux for you.
Instead, test your action creators by themselves in unit tests.
Then, export your component as named export without connecting and use the default export for the connect version.
That way you can simply import the pure-React version and pass anything you want as props, in order to make easy assertions afterwards.
If you need to specifically test that something happens in those lifecycle methods, you can call those methods from the instance:
const fakeActionCreator = sinon.spy()
const subject = mount(<MyComponent doSomething={ fakeActionCreator } />)
subject.instance().componentDidMount()
assert.equal(fakeActionCreator.callCount, 1)

Grails Unit Testing Issues

I am having issues while testing my grails controllers, as it depends on one service which seems not to be injected. I tried several ways (for ex. Extending classess like grailsunitestcase, specification) but I keep getting errors. The thing is that that service variable is null and I cant test my controller index method (which calls a render view) due to the exception...
I really need to know how to do this but I don't have a clue where to start...
Unit tests are just that. There is no grails 'environment' surrounding your controller. If the controller makes use of a service which is normally injected, you have to mock that service yourself.
#TestFor(SomeController)
#Mock([SomeService])
class SomeControllerSpec extends Specification
def "test some method"() {
given:
def mockService = mockFor(SomeService)
mockService.demand.someServiceMethod() { ->
return something
}
controller.someService = mockService.createMock()
when:
controller.someControllerMethod()
then:
// whatever checks are appropriate
}
}

Unit testing Promise task in grails

How do we unit test logic in Promises.task?
task{service.method()}
I want to validate invocation of the service method inside the task.
Is this possible? If yes, how?
I read in the documentation that in unit testing async processes, one can use this:
Promises.promiseFactory = new SynchronousPromiseFactory()
Tried adding it in my setup, but still does not work.
The long way
I've been struggling with this for a moment too.
I tried those:
grails unit test + Thread
Verify Spock mock with specified timeout
Also tried the same solution from the docs as you:
Promises.promiseFactory = new SynchronousPromiseFactory()
All went with no luck.
The solution
So I ended up with meta classing.
In the test's setup method, I mocked the Promise.task closure, so it runs the closure in the current thread, not in a new one:
def setup() {
Promises.metaClass.static.task = { Closure c -> c() }
// ...more stuff if needed...
}
Thanks to that, I can test the code as it wouldn't use multi threading.
Even I'm far from being 100% happy with this, I couldn't get anything better so far.
In recent versions of Grails (3.2.3 for instance), there is no need to mock, metaClass or use a Promise factory. I found out the promises in unit tests get executed synchronously. Found no doc for that, I empirically added a sleep inside a promise and noticed the test waited for the pause to complete.
For integration tests and functional tests, that's another story: you have to change the promise provider, for instance in BootStrap.groovy:
if (Environment.current == Environment.TEST) {
Promises.promiseFactory = new SynchronousPromiseFactory()
}
Like Marcin suggested, the metaClass option is not satisfactory. Also bear in mind that previous (or future) versions of Grails are likely to work differently.
If you are stuck with Grails 2 like dinosaurs such as me, then you can just copy the classes SynchronousPromiseFactory and SynchronousPromise from Grails 3 to your project and then the following works:
Promises.promiseFactory = new Grails3SynchronousPromiseFactory()
(Class names are prefixed with Grails3 to make the hack more obvious)
I'd simply mock/override the Promises.task method to invoke the provided closure directly.

how to mock a service method inside a controller for unit testing in grails using JUnit and when to use mockController

Help me understand how to mock a service method inside a controller for unit testing in grails using JUnit
I was trying to write a unit test case for my controller "add".
void testAdd_UT_03(){
......declaring and assigning prerequisites
controller.add() // This is the controller i want to unit test
.... asserting
}
//Controller
def add{
def a =someService.method()
}
Inside controller, some service methods are getting called which in turn is using HQL statements. Since i could not find a way to deal with HQL statements in unit testing, i want to mock the service method itself. ( i want the service method to return the predefined output).
Could someone please explain how to achieve this?
Could you also explain when to use mockController? what we really achieve by mocking something? ( i dint get the real picture as i am entirely new to this)
Thanks in advance,
BK
you can add the following code in the setUp method of your test to mock the service method and when you call the method "add" method on your controller it will call the mocked service method.
def predifinedOutput
void setUp(){
def mockControl = mockFor(YourService)
//params are the parameters passed to the service method
mockControl.demand.yourServiceMethod(0..10) { params->
predifnedOutput = "predifinedOutput"
return "predefined output"
}
controller.yourService = mockControl.createMock()
}

How do I write test(s) for this in Symfony?

I'm about to delve into test in the PHP world and I have some questions. I have a controller which handles a loan application. The bulk of the work is then delegated to a ProcessLoanApplication class.
ApplyController
class ApplyController extends Controller
{
public function indexAction(Request $request)
{
$form = $this->createForm(new LoanApplication());
if($request->getMethod() == 'POST') {
$form->bind($request);
if($form->isValid()) {
$session = $this->getRequest()->getSession();
$loan_app_processor = new Tasks\ProcessLoanApplication($form, $session);
$loan_app_processor->process();
return $this->redirect($this->generateUrl('apply_thanks'));
}
}
Tasks\ProcessLoanApplication
class ProcessLoanApplication
{
private $_QuickBaseModels;
private $_session;
private $_app; // submitted form data
private $_existingApp = false; // holds existing application in QB, if it exists
public function __construct(Form $form, Session $session)
{
$this->_app = $form->getNormData();
$this->_session = $session;
// save the form data to a session
$session->set('application', $this->_app);
// create the quickbase table models objects
$this->_QuickBaseModels['GenFnHome\Application'] = new GenFnHome\Application();
$this->_QuickBaseModels['GenFnHome\SSN'] = new GenFnHome\SSN();
}
public function process()
{
$this->_existingApp = $this->_getExistingApplication();
$app_status = $this->_existingApp[GenFnHome\SSN::LogInApplicationStatus];
if(!$this->_existingApp || ($this->_existingApp && ($app_status !== 'PENDING' && $app_status !== 'OPEN' && $app_status !== 'EXPIRED')))
return $this->_saveNewLoanApplication();
if($app_status == 'EXPIRED') $this->_reOpenApplication();
}
There's a lot going on here, so I will outline it first:
User makes a requests for the application
Application form is validated
If valid, process loan application
Check if the user already has an app, if so - do X, if not Y
The application is persisted in an 'online database' (QuickBase) that my application communicates with via XML over HTTP (in other words, there is no real db)
My questions to the community:
What should be tested here? I know it is largely up to me, but perhaps the community can recommend some baseline tests that should def be written. Should I be testing the controller, the processor class, and the QuickBase class?
Should my tests be independent of one another - meaning, I should test each component individually, rather than have one massive testApplication that does everything the indexAction does and just looks for the expected sessions vars that get set?
Finally, how does one test API calls (request / response) without actually making real request (I'm using PHPUnit).
Anything else I should know?
Thanks!
What should be tested here? I know it is largely up to me, but perhaps the community can recommend some baseline tests that should def be written. Should I be testing the controller, the processor class, and the QuickBase class?
I recommend to test every class you build. If you are using Test Driven Development, the test declares what you are building, no test no code.
Should my tests be independent of one another - meaning, I should test each component individually, rather than have one massive testApplication that does everything the indexAction does and just looks for the expected sessions vars that get set?
Every Unit test should be isolated and should only test the Class that you are testing. You should use Mock object (use the PHPunit mock library or other 3th party libraries as Mockery) if one object dependences on another object.
Finally, how does one test API calls (request / response) without actually making real request (I'm using PHPUnit).
You can use the Symfony's WebTestCase that provides easy methods to imitate a browser request, learn more about that in the documentation. We call that Functional Testing.
This is usually the stage after Unit Testing. In Unit Testing you will test each individual class (it's a good practice to unit test your controller) and after that you write your Functional Tests which combines everything and tests if it works like expected.
for Controllers you should use functional tests (http://symfony.com/doc/2.0/book/testing.html#functional-tests). With them you can emulate browser and user's actions like submiting form and checking validation, database changes, http status codes and so on.
You should not forget to unit test ProcessLoanApplication.
I dont realy know why you pass form object to ProcessLoanApplication anyway. You should pass entity - it has normdata already.