I wanted to test the models of my Trails.js project with mocha. I use the trailpack-waterline to load my models into the Waterline ORM.
Following the Trails Docs I created a User.test.js:
'use strict'
const assert = require('assert')
describe('User Model', () => {
let User
before(() => {
assert(global.app.models.User)
User = global.app.models.User
})
it('should exist', () => {
assert(User)
})
})
This runs without any error.
But I cannot instantiate the model in any way. Following the example of the Docs new User({...}) should create a new user object, but this code throws an error saying User is not a constructor. And neither the example of the Waterline Docs using User.create({...}) seems to work.
Printing out the User model shows it consists of only two methods: [ 'getModelName', 'getTableName' ].
How do I instantiate a waterline Model for unit testing?
It's because global.app.models.User is your model's definition and not the waterline model. This one is under global.app.orm.User, after that you can use User.create without any problem
Related
I'm using sequelize v5.21 and sequelize-cli v5.5.1 for a MySQL database.
I'm currently trying to create some association 1:M under the following model generated code from the cli like so:
Where: a is the source and b the target.
model.associate = function (models) {
// associations can be defined here
a.hasOne(models.b);
}
and the other model, i have:
model.associate = function (models) {
// associations can be defined here
b.belongsTo(models.a);
}
Finally, im using this code to check the associations by creating a entries:
a.create({
...
}).then(a => {
return a.createB({
...,
}).catch(err => console.log(err));
}).catch(err => console.log(err)
);
In which i'm getting an error on the "a.createB()..." as is not a function...
So, i was curious enough and tried doing the associations right before checking the associations like so:
a.hasOne(b);
b.belongsTo(a);
In which works just fine...
My question is, is the "model.associate" property still working on the v5^?
Note: I have used the check associations method provided in the sequelize documentation but i prefer this one since it's easier to read.
I found nothing about model.associate in Sequelize documentation for v5, but in my project I'm using this code in main models directory:
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
where db is autogenerated by sequelize-cli models imported by sequelize['import']
I have a very simple app showing a login screen and a dashboard. When the login is successful the app navigates to the dashboard.
In this state, a back navigation (android) should not go back to the login screen.
This all works fine using the IonicHistory
this.$ionicHistory.nextViewOptions({
disableBack: true
});
return this.$state.go("dashboard");
This is all done in my LoginCtrl when the SessionService (which does the login call to the service and the Session management...) resolves the returned promise.
Now I want to write a Unit-Test to check this behaviour and make sure, never every removes this nextViewOptions-call.
My idea is something like this:
beforeEach(() => {
angular.mock.module("ionic");
angular.mock.module("myapp");
inject(function ($q: IQService, $rootScope: IScope, $ionicHistory: IonicHistoryService): void {
qService = $q;
scope = $rootScope;
ionicHistory = $ionicHistory;
});
});
describe("login", () => {
// Stub my sessionservice to immediatly resolve instead of doing a request
sinon.stub(sessionService, "login", () => qService.when());
let loginCtrl: LoginCtrl = new LoginCtrl(sessionService, stateService, ionicHistory);
loginCtrl.executeLogin();
scope.$apply();
// Here I want to validate, that the history (and therefore the back-stack) is correct.
// But the ionicHistory.viewHistory() does not change at all.
// Independent whether I add the nextViewOptions stuff or not...
}
Here the output from ionichHistory.viewHistory().histories:
Object{root: Object{historyId: 'root', parentHistoryId: null, stack: [], cursor: -1}}
I use the karma test runner to execute the tests.
I'm using:
Ionic 1.3.0
Karama Test Runner
TypeScript
Is this actually possible at all? Do I miss something completely?
I have a REST API and one of my test requires certain resources to have been created by another API... The example below demonstrates the pattern.. Questions are
Is this an appropriate patter to use with Mocha
If so, how would you recommend I get the ID of the created user into my account test case?
Other recommended approaches?
userTest.js
exports.createAdminUser = function(done) {
request.post( ... );
expect(res.location).to.eql(...);
// Now I've created an admin user
};
describe('User Tests', function() {
it('creates an admin user', createAdminUser);
it('modifies the admin user', ...);
...
}
This I have another test for accounts, which must have a user setup. I don't want to do this work again for each of these types of dependent tests
Accounts Test
-------------
var userTests = require('../users/userTest.js');
describe('Account Tests', function() {
it('creates an admin user to prime the database', userTests.createAdminUser);
it('creates a checking account', function(done){
// Here I need to know the ID of the admin user to use in my POST req.
});
}
I don't mean remove a document or documents. I mean remove the model entirely so that mongoose is no longer aware of it. After declaring a model I can't figure out how to make mongoose forget that model so that it could be recreated.
mongoose.model('Book', bookSchema);
mongoose.model('Book', bookSchema);
Currently the above throws an exception.
OverwriteModelError: Cannot overwrite 'Book' model once compiled.
I'd like to be able do something like this...
mongoose.model('Book', bookSchema);
mongoose.removeModel('Book');
mongoose.model('Book', bookSchema);
...and not get any errors. Any ideas?
try this
delete mongoose.connection.models['Book'];
and then re-register/re-initialize it . it will work fine
It appears that you'd have to overwrite some of the source code in order to be able to remove a model an add a new one since Mongoose makes sure that a model doesn't exist before it's willing to create a new one, which may or may not be more than you care to do:
if (this.models[name] && !collection) {
// model exists but we are not subclassing with custom collection
if (schema instanceof Schema && schema != this.models[name].schema) {
throw new MongooseError.OverwriteModelError(name);
}
return this.models[name];
}
Line 587 https://github.com/LearnBoost/mongoose/blob/master/lib/connection.js
Question Author's Update:
Thanks to this answer I discovered that you can access the models defined on the connection through connection.models. In my scenario I was testing a mongoose plugin with Mocha and and I wanted to clear the models between each unit test.
afterEach(function () {
mongoose.connection.models = {};
});
You can use the deleteModel method
mongoose.deleteModel(modelName);
This is actually a better way to get rid of models, schemas and collections in mongoose
mongoose.connections.forEach(connection => {
const modelNames = Object.keys(connection.models)
modelNames.forEach(modelName => {
delete connection.models[modelName]
})
const collectionNames = Object.keys(connection.collections)
collectionNames.forEach(collectionName => {
delete connection.collections[collectionName]
})
})
const modelSchemaNames = Object.keys(mongoose.modelSchemas)
modelSchemaNames.forEach(modelSchemaName => {
delete mongoose.modelSchemas[modelSchemaName]
})
Reference: https://github.com/Automattic/mongoose/issues/2874#issuecomment-388588452
I'm working on unit testing an EmberJS project with Jasmine but I'm having trouble with Ember's needs API.
When I try to run the jasmine tests, they fail on creating a controller instance, if the controller in question has "needs" as well as an init function that calls
this._super()
I get this console error
"Cannot call method 'has' of null"
that when I tried to debug, brought me all the way into the bowels of Ember but I got nowhere with that.
Anyone have any idea what I'm doing wrong
Application.SearchPendingController = Ember.ObjectController.extend({
needs: ['searchResults', 'search'],
shouldDisable: false,
searchResultsController: null,
init: function () {
this._super();
this.set('searchResultsController', this.controllerFor('searchResults'));
this.get('controllers.search.content').reload();
this.get('controllers.searchResults').set('content', this.get('controllers.search.content.results'));
},
transitionToResults: function () {
console.log('yay');
}.observes('this.searchResultsController.content')
});
The jasmine tests throw an error when I try to create this controller
var searchPendingController = Application.SearchPendingController.create();
Anyone have any ideas about this?
When you create a controller, Ember.js checks the dependencies (needs) in the init method. Checking for dependencies assumes you have an Ember.js application, and this application's container is found in the container property of the controller. This all works great if Ember.js created the controller for you.
Your error is happening here, in the verifyDependencies function.
If you don't want Ember.js to create the controller for you and want to create it manually, (which is what you are doing here), you will need to manually set the controller's container property to the application's container.
Application.SearchPendingController.reopen({
container: Application.__container__
});
Unit testing controllers is tricky and requires that you dive into the internals of Ember.js. My advice, let Ember.js create the controllers for you, and use integration tests instead of unit testing them.
Even better is if your controller needs to access the other controller for calculating some property is to have the container create the controllers for you.
Application.SearchPendingController = Ember.ObjectController.extend({
needs: ['searchResults', 'search'],
Testing
var searchModel = something,
searchResultsModel = something,
searchPendingModel = something;
var container = Application.__container__,
searchController = container.lookup('controller:search'),
searchResultsController = container.lookup('controller:searchResults'),
searchPendingController = container.lookup('controller:searchPending'),
searchController.set('model', searchModel),
searchResultsController.set('model', searchResultsModel ),
searchPendingController.set('model', searchPendingModel );