Using DrupalUnitTestCase to unit test a Drupal module, fails. I probably forget something.
The test runs fine untill I create an instance of some class:
$foo = new FooBar();
In that case, Drupal decides to do some magic and attempts to call the database, in order to find some file in its registry.
Test PDOStatement->execute() failed: <em class="placeholder">PDOException</em>: SQLSTATE[42S02]: Base table [error]
or view not found: 1146 Table 'td_development.simpletest50921registry' doesn't exist: SELECT
filename FROM {registry} WHERE name = :name AND type = :type; Array
(
[:name] => FooBar
[:type] => interface
)
DrupalUnitTestCase, as opposed to DrupalWebTestCase do not set up a database, by design. So the reason why this fails is clear.
However, I don't want Drupal to go looking in a database when all I want is to create some instance. How to avoid Drupal looking up the file in its registry?
You probably can't.
The possibilities of using UnitTestCase as the parent class are very limited. As soon as you do anything that requires the database (and creating a new class does because the autoload features of Drupal 7 depend on the database), you have to use WebTestCase.
The only thing that might work is explicitly including all files that are required for that class to work. Because the autoload is only called if the class does not exist yet (could also be a class that your class uses or depends on). But that is relatively fragile and you will always have to include all these files manually in the correct order, which means that your unit tests depend on the inner workings of your class. Which isn't nice either.
You can also try this
spl_autoload_register('your_function');
if (function_exists('drupal_autoload_class')) {
spl_autoload_unregister('drupal_autoload_class');
spl_autoload_register('drupal_autoload_class');
spl_autoload_unregister('drupal_autoload_interface');
spl_autoload_register('drupal_autoload_interface');
}
This will move the Drupal autoload to the bottom and solve the problem.
Related
Creating in-repo-addon in Ember.JS gives a lot of possibilities. Today I've stumbled into a case when I wanted to register all classes in directory (for example my-dir) into Dependency Injector (same way it's done with services by Ember, but I wanted to use some other namespace).
For example I want to allow developer to create multiple classes inside proxy directory, and register all of them in DI under proxy: namespace. So later we can use:
Ember.Component.extend({
myProxy: Ember.inject('proxy:my'),
});
You'll need to do this using an initializer. More details on this here: https://guides.emberjs.com/v2.12.0/applications/dependency-injection/
The hard part may be getting all proxy items in s folder to automatically register ...
Edit
Looks like I didn't spend enough time thinking about this. You should be able to do at least part of this easily. There are two parts to this.
Part 1
Ember currently uses the ember-resolver to handle lookups for various items. If you check the tests for the resolver you'll notice that you should be able to map in anything you want: https://github.com/ember-cli/ember-resolver/blob/master/tests/unit/resolvers/classic/basic-test.js
So in your case, if you do a Ember.getOwner(this).lookup('proxy:main') from within an Ember instantiated class (a route, controller or component for instance) it would look in app/proxy/main.js which your addon could be populating.
Details on the Ember.getOwner lookup are available here: https://emberjs.com/api/classes/Ember.html#method_getOwner
Part 2
So at this point you can lookup proxies (which would be doable in an init method). But if we want to get truly elegant we'd want to allow Ember.inject.proxy('main') syntax.
Doing so would involve calling a private method inside of Ember.inject in an initializer. Because that naming scheme is changing in the new Javascript modules RFC, it may be unwise to try to add this syntactic sugar ...
So I'd advise avoiding touching that private API unless it's really important to your app design.
I am struggling with how to dynamically add some webservices. I am using Scalatra for the webservice framework.
I want to allow the developer to be able to change authentication, for example, so that rather than using hard-coded credentials, instead use a database or password file or whatever they need.
I also want to allow them to add new webservices inside the servlet.
So, what I want to do is in the bootstrap code have it load up and recompile the class and then use that version.
I have looked at this, but I need to recompile an entire class, not snippets.
Generating a class from string and instantiating it in Scala 2.10
This is what I have tried, but I added a "/help" webservice but it isn't found, so the new class isn't being used yet.
class ScalatraBootstrap extends LifeCycle {
override def init(context: ServletContext) {
val sourceDir = new java.io.File("C:/Temp/MyServlet.scala")
val sse = ScalaScriptEngine.onChangeRefresh(sourceDir)
sse.refresh
println("*** - " + sse.compilationStatus.startTime + " " + sse.compilationStatus.stopTime)
context.mount(sse.get[MyServlet]("test.proj.MyServlet"), "/*")
I am using scalascriptengine (https://code.google.com/p/scalascriptengine/) at the moment.
So, how can I recompile the class file for the webservice, when it may have case classes, annotations and object classes in the same file, on the fly?
I am wondering if I need to have the webservice in Groovy instead, but I would prefer to keep it functional.
UPDATE
I had thought about plugins first, but ran into a problem with how would I add new webservices that way, and it may be that Scalatra is not going to be the right choice, that I may need to change my REST service framework.
Eventually I want to be able to change the webservices on the fly without having to restart the application, and recompiling the source would allow that.
Realizing a plug-in affordance is not too hard, at least for reasonably simple cases. The essential elements are:
A trait or abstract class defining the obligations of realizations of the plug-in.
A means to get the code for plug-ins onto the class-path. Alternatively, if you're familiar with working with classloaders, you can do it dynamically. I don't have much experience with that.
Once you have an instance of java.lang.Class[P <: PlugInType] it's trivial to get an instance, provided you don't need constructor parameters.
A protocol in the plug-in trait that allows the plug-in to, e.g., reserve a top-level URL path segment from which you derive a Scalatra route that covers all those paths. You then dispatch requests that match that leading path segment via the plug-in instance. All you have to do is make sure you don't let two plug-ins claim the same path or if you do you have some further means of resolving them.
Thanks to #RandallSchultz I found a solution that works.
override def init(context: ServletContext) {
val sourceDir = new java.io.File("C:/Temp/HelpServlet.scala")
val sse = ScalaScriptEngine.onChangeRefresh(sourceDir)
sse.refresh
println("*** - " + sse.compilationStatus.startTime + " " + sse.compilationStatus.stopTime)
context.mount(new MyServlet, "/*")
context.mount(sse.get("org.myproject.rest.HelpServlet"), "/help/*")
So when I went to "/help/help" I got my help page as expected, so the new webservice was added.
By reading it from a file I was able to add it while the application was running.
I make an application writed in Rails, it's growing fast and I learning with it. But I'm don't understand about helpers.
application_helper.rb
module ApplicationHelper
# This file it's empty
end
users_helper.rb
module UsersHelper
def avatar
# Do something
end
end
customer_helper.rb
module CustomerHelper
# This file it's empty
end
Why in any customer's view can call avatar helper method on user helper module?
Then, why separate helpers in many files?
Thanks in advance.
P.S: Rails' version 4.
Because all helpers are included in all controllers, by default. The separate files are really just for logical separation in this scenario. You can change that behaviour though:
By default, each controller will include all helpers.
In previous versions of Rails the controller will include a helper
whose name matches that of the controller, e.g., MyController will
automatically include MyHelper. To return old behavior set
config.action_controller.include_all_helpers to false.
http://api.rubyonrails.org/classes/ActionController/Helpers.html
To add to Mike Campbell's answer:
Framework
As magic as it is, Rails is a set of files which are called
sequentially
These files hold classes, methods, etc; but they're still files.
And that means that when you run an action through Rails, it loads up
a series of other dependent files to help it run (that's what a
framework is)
The design of Rails is such that your helper methods are all
loaded each time you run an action. I don't know why, but it helps
administer the methods for different areas of your app
So to answer your question, there's no real reason why the helpers are split up, at least with Rails 4
So I'm working on some unit tests and relational fixtures.
I'm creating a model dynamically like:
$model = CActiveRecord::model('Post');
$post = $model->findByPk(1);
But after that I cannot for some reason get $post->id. I traced the problem to CActiveRecord class:
public function __get($name)
{
if(isset($this->_attributes[$name]))
return $this->_attributes[$name];
...
Where $name = "id". It says that $this->_attributes[$name] does not exist! As a matter of fact _attributes is empty.
My Post class does not define id (or any other properties) as a public property and I don't want to do so either. I just let the AR map it to table columns for me.
What am I missing?
Edit 1
My fixtures are regular Yii fixtures - nothing really special about them.
What differs is the way I load them really. I extended the CDbFixtureManager to be able to specify the order in which they should be loaded by overloading load() method. Only thing of interest that actually fails is that in the fixtures that have foreign keys I use the following:
'comment1' => array('post_id' => $this->getRecord('Post', 'post1')->id);
That's where it fails. getRecord returns the actual Post record (since I know the Post fixture has already been successfully loaded and exists in DB), but on the ->id part I get an exception about that attribute not existing.
If I go into Post model and add public $id; to it, then everything works! But I'm not sure if it's good practice to go about declaring all properties public like that.
If you look at this page carefully:
http://www.yiiframework.com/doc/guide/1.1/en/test.unit
you'll see that they use an array form for retrieving fixtures:
$this->posts['sample1']['id']
There is an alias defined in their fixture array for each record and fixture items aren't loaded as models really ...
Does that help? If not, it would be helpful to see your fixture file :-)
I think I found the root cause of this issue for me. While my FixtureManager was using the testdb DBConnection, the models still used the regular one.
For whatever reason, my debugger was giving me misleading errors like the one described in my original post.
Once I was able to set the DBConnection of all Models in the unit test the puzzle snapped into place and everything is now working smoothly!
I'm using the entity framework.
In one of my unit tests I have a line like:
this.Set<T>().Add(entity);
On executing that line I get:
System.InvalidOperationException : The model backing the
'InvoiceNewDataContext' context has changed since the database was
created. Either manually delete/update the database, or call
Database.SetInitializer with an IDatabaseInitializer instance. For
example, the DropCreateDatabaseIfModelChanges strategy will
automatically delete and recreate the database, and optionally seed it
with new data.
Well I've actually deleted the database and removed the connection string.
I'm surprised this error is happening on adding as I wouldn't expect it to happen until I saved the data and it discovered there was no database.
In previous projects/solutions I created during unit tests I have been able to add to the context for test purposes without actually calling SaveChanges.
Would anyone know why this would be happening in my latest projects/solutions?
Are you sure it really didn't use database in your previous projects? If you do not specify any connection string it will silently use a default one to SQLExpress database with local .mdf file so make sure that isn't happening now.