How do I scope a variable so that its available to other functions in the same CFC (a CFWheels plugin)? - coldfusion

I want to add a variable that can be accessed by all functions in a plugin, but I'm getting a variable undefined error. Here's my plugin:
component
mixin="Controller"
{
public any function init() {
this.version = "1.0";
return this;
}
public void function rememberMe(string secretKey="rm_#application.applicationName#") {
this.secretKey = arguments.secretKey;
}
public void function setCookie(required string identifier) {
// Create a cookie with the identifier and encrypt it using this.secretKey
// this.secretKey is not available, though, and an error is thrown
writeDump(this.secretKey); abort;
}
}
I call the plugin from my Sessions.cfc controller:
component
extends="Controller"
{
public void function init() {
// Call the plugin and provide a secret key
rememberMe("mySecretKey");
}
public void function remember() {
// Call the plugin function that creates a cookie / I snipped some code
setCookie(user.id);
}
}
When I dump this.secretKey inside the plugin, I get a variable undefined error. The error tells me that this.secretKey is not available in Sessions.cfc controller. But I'm not dumping from Sessions.cfc, I'm dumping from the plugin's CFC, as you can see. Why?
How can I scope this.secretKey in my plugin so that it can be accessed by setCookie()? So far variables and this have failed, whether I add the definitions in a function, a pseudo-constructor, or the init(). For good measure, I threw in variables.wheels.class.rememberME, to no avail.
Here's the error:
Component [controllers.Sessions] has no acessible Member with name [secretKey]

What you're doing in init() isn't going to work when in production mode. A controller's init() is only run on the first request for that controller because it get cached after that.
So this.secretKey will be set on the very first run of that controller but never for subsequent runs.
You have a few options to make this work...
I. Use the pseudo-constructor, which does run on every controller request:
component
extends="Controller"
{
// This is run on every controller request
rememberMe("mySecretKey");
// No longer in `init()`
public void function init() {}
public void function remember() {
// Call the plugin function that creates a cookie / I snipped some code
setCookie(user.id);
}
}
II. Use a before filter to call on every request:
component
extends="Controller"
{
// No longer in `init()`
public void function init() {
filters(through="$rememberMe");
}
public void function remember() {
// Call the plugin function that creates a cookie / I snipped some code
setCookie(user.id);
}
// This is run on every request
private function $rememberMe() {
rememberMe("mySecretKey");
}
}
III. Store the key in a persistent scope so that calling it only once from the controller's init() is OK.
component
mixin="Controller"
{
public any function init() {
this.version = "1.0";
return this;
}
public void function rememberMe(string secretKey="rm_#application.applicationName#") {
application.secretKey = arguments.secretKey;
}
public void function setCookie(required string identifier) {
// This should now work
writeDump(var=application.secretKey, abort=true);
}
}

Related

how can i store the value returned by my init to be used in my functions

I have the init code and it returns me a structure
public any function init() {
httpService = new http();
httpService.setUrl("#Application.baseURL#security/oauth2/token");
httpService.setMethod("POST");
httpService.addParam(type="header", name="Content-Type", value="application/x-www-form-urlencoded");
httpService.addParam(type="body", value="client_id=#application.clientID#&client_secret=#application.clientsecretID#&grant_type=#application.grant_type#");
result = httpService.send().getPrefix();
return this;
}
problem how can i use the token returned by the method in other methods, if i dump the init, i am just getting the functions, how can i use the data returned by the http
just not getting in my head, because the token is alive for 3600
Thanks
As James says, you should store the result of the http call as an instance variable. Here's one way of doing it using a property and specifying accessors=true for the component so that you can call setHttpResult() and getHttpResult() without having to write those methods. using the variables scope which will make it available to other methods within the component, but not outside.
/* Test.cfc */
component name="test"{
property name="httpResult" type="struct";
public any function init(){
//use "var" to ensure the variable is local to the function only
var httpService = new http();
httpService.setUrl("#Application.baseURL#security/oauth2/token");
httpService.setMethod("POST");
httpService.addParam(type="header", name="Content-Type", value="application/x-www-form-urlencoded");
httpService.addParam(type="body", value="client_id=#application.clientID#&client_secret=#application.clientsecretID#&grant_type=#application.grant_type#");
//store the result privately in the instance
variables.httpResult = httpService.send().getPrefix();
return this;
}
public void function someOtherMethod(){
// this method can access the result struct
var returnedContent = variables.httpResult.fileContent;
}
}
You can then use getHttpResult() inside or outside your component. For example from an external script:
test = New test(); // calls the init() method
WriteDump( test.getHttpResult() ); //auto-generated "getter"

BDD Mockito - alias for verify(...) when using argument captor?

I wrote the test which uses BBDMockito and Argument Captor. Argument Captor is used only to capture callback and invoke onDataNotAvailable(), not for the verification.
#Test
public void loadNoItemFromRepository_showsMissingItem() {
//given
itemDetailPresenter = new ItemDetailPresenter(UNCHECKED_ITEM.getId(), itemsRepository, itemDetailView);
given(itemDetailView.isActive()).willReturn(true);
//when
itemDetailPresenter.load();
verify(itemsRepository).getItem(eq(UNCHECKED_ITEM.getId()), getItemCallbackArgumentCaptor.capture());
getItemCallbackArgumentCaptor.getValue().onDataNotAvailable();
//then
then(itemDetailView).should().showMissingItem();
}
Verify placed in //when section is confusing because the name suggests it should be placed in the verification section (//then). Is there an alias for verify() so I can use it with argument captor and the name will be more appropriate for //when?
Edited:
The code which I want to test is if itemDetailView.showMissingItem() was called.
public void load() {
(...)
itemsRepository.getItem(itemId, new ItemsDataSource.GetItemCallback() {
#Override
public void onItemLoaded(Item item) {
(...)
if (nonNull(item))
showItem(item);
else
itemDetailView.showMissingItem();
}
#Override
public void onDataNotAvailable() {
(...)
itemDetailView.showMissingItem();
}
});
}
verify(...) is an assertion, it's used to check a method was/wasn't called and how many times - it belongs in the //then section
I see you're also using an argumentCaptor but aren't checking anything with it, the proper process there would be to assert that the captured value (getItemCallbackArgumentCapture.getValue() contains/equals a value you expect).

How to verify to call or not to call a method

class MockView extends Mock implements ContactListViewContract {
#override
void onLoadContactsComplete(List<Contact> items) {
}
#override
void onLoadContactsError() {}
}
void main() {
test('ContactListPresenter test', () {
Injector.configure(Flavor.MOCK);
MockView view = new MockView();
ContactListPresenter presenter = new ContactListPresenter(view);
presenter.loadContacts();
verify(view.onLoadContactsComplete).called(1);
});
}
I want to make sure when presenter.loadContacts() is called from the code, then verify view.onLoadContactsComplete is called also but getting an error:
Used on a non-mockito object
Is there a possibility to do this with Mockito?
Update:
abstract class ContactListViewContract {
void onLoadContactsComplete(List<Contact> items);
void onLoadContactsError();
}
here the onLoadContactsComplete method is called
class ContactListPresenter {
ContactListViewContract _view;
ContactRepository _repository;
ContactListPresenter(this._view){
_repository = new Injector().contactRepository;
}
void loadContacts(){
assert(_view != null);
_repository.fetch()
.then((contacts) {
print(contacts);
_view.onLoadContactsComplete(contacts); // here the onLoadContactsComplete method is called
}).catchError((onError) {
print(onError);
_view.onLoadContactsError();
});
}
}
Mocked Repository. Fetch mocked data.
class MockContactRepository implements ContactRepository{
Future<List<Contact>> fetch(){
return new Future.value(kContacts);
}
}
when calling verify method you need call the actual method on the mock
Try
test('ContactListPresenter test', () async {
Injector.configure(Flavor.MOCK);
MockView view = new MockView();
ContactListPresenter presenter = new ContactListPresenter(view);
presenter.loadContacts();
await untilCalled(view.onLoadContactsComplete(typed(any)));
//completes when view.onLoadContactsComplete(any) is called
verify(view.onLoadContactsComplete(typed(any))).called(1);
});
If the method was not called once, the test will fail.
Mockito provides native support for both
To test that your method has been called at least once you can use
verify(<your-method-with-expected-params>) this will verify that your method has called (no matter how many times). To verify that it has been called for a specific number of times you can chain it with .called(<number-of-calls-expected>)
To test that your method hasn't been called you should use verifyNever(<your-method-with-expected-params>) this will validate that your method hasn't been invoked
Make sure that the method passed to both verify and verifyNever are the methods which have been Mocked by Mockito.
You can use never and verifyZeroInteractions
//interaction with mockOne
mockOne.add("one");
//ordinary interaction
verify(mockOne).add("one");
//we never interaction into the mock
verify(mockOne, never()).add("two");
//verify we don't use in the mock
verifyZeroInteractions(mockTwo, mockThree);
*mark verifyZeroInteractions as deprecated in mockito-kotlin, too
introduce an alias for verifyNoInteractions

Laravel testing - Problems with created routes

I have a question about routing while testing packages. The function setRoutes creates new routes in the test file as follows:
class PackageTests extends \Orchestra\Testbench\TestCase {
protected function setRoutes()
{
Route::group([
'prefix' => Package::functionToCall1(),
'before' => 'filter'
], function() {
Route::get('/', function () {
return "hello";
});
});
Route::enableFilters();
}
protected function getEnvironmentSetUp($app)
{
$this->app = $app;
$this->setRoutes();
Config::set('app.url', "http://localhost/" );
}
public function testFunction1()
{
$crawler = $this->call(
'GET',
'http://localhost/'
);
// doing this call, the function on the prefix is called
$this->assertResponseOk();
}
}
Inside the function called in the prefix, functionToCall1() urls are not taken successfully. A call to URL::current() returns "/" and a call to Request::fullUrl() returns "http://:" when phpunit is executed but they returns the full url when used executing a url in the browser. This is the code of the package:
class Package
{
function functionToCall1()
{
var_dump(URL::current() ); // returns "/"
var_dump(Request::fullUrl()); // returns "http://:"
// I want them to return 'http://localhost'
}
}
I tried setting up the url Config::set('app.url', "http://localhost/" ); but it was useless.
To sum up, is there a way to call a function in the prefix and get the testing url?
Thanks, I would really appreciate your answers :)
I have had to deal with a similar issue. My solution was found here:
Mocking Laravel's Request::segment method
Apparently there is an order of operations issue with testing a Request facade.
I was trying to use Request::segments() before the request was being built, so there were never any segments to return.
I imagine it's the same problem with Request::fullUrl().
Here is my solution:
class MyTestClass extends TestCase
{
public function setUp()
{
// No call to parent::setUp()
$this->app = $this->createApplication();
$this->app->request->server->set('REQUEST_URI', '/some/uri');
$this->client = $this->createClient();
$this->app->boot();
}
public function testWhatever()
{
$this->call('GET', '/some/uri');
}
}
This allows me to get the request data properly, even though it looks pretty bad.

How to mole or moq e particular function which gets called in a static function

I want to test a particular function.
That function has call to static method of a different class which is protected thus cannot be access from outside.
As I am doing component level testing I don't want to hit the database.
So is it possible to mock a particular call to database if its inside a static function.
//I want to test this function
public void testing
{
Abc.instance.Add();
}
class Abc
{
public static readOnly instance = new Abc();
Abc()
{
createInstance();
}
public void createInstance()// I want to mock this function
{
//calls to the database
}
public void Add()
{
//...
}
}
But even if I use delegate to mock createInstance() , before even going to delegate line , static block is getting called, thus hitting the database and an exception is thrown.