Abstract classes using mongoose

I am developing an application in which I need to have some abstraction.

I mean, I would like to "mimic" the behavior of an interface, for example, creating a contract inside my specific classes.

Actually, when dealing with Users, I have a UserMongoRepository class with an implemented contract:

  • getAll () returns a complete list of users by promise
  • getById (id) returns the interested user by promise
  • save (user) saves the user as promised
  • ... etc.

I have the same methods implemented inside UserMysqlRepository (allowing me to switch behavior when a change is required.

Problem

My problem is that I am dealing with Mongoose, which does not act as a datamapper, but rather as an active record.

This means that my save (user) implementation will be a bit strange:

save(user){ let mongooseUser = this.convert(user); return user.save(); } 

The conversion method allows me to move from a standard model to a specific Mongoose model. This allows me to have an abstraction again and not to rewrite my full access to application data.

My real problem is when I try to unit test my full class:

 import MongooseUser from '../../auth/mongooseModel/MongooseUser'; /** * UserMongoRepositoryclass */ export default class UserMongoRepository{ /** * Create an UserMongoRepository */ constructor(){ } /** * Convert a User to a MongooseUser */ convert(user){ return new MongooseUser({email:user.mail,password:user.password,firstname:user.firstName, lastname:user.lastName}); } findById(id){ return MongooseUser.find({id:id}); } save(user){ return user.save(); } } 

In a standard way, I would enter my DAO inside my constructor and be able to mock it.

In the case of the mongoose, this is a bit of a concern, because the element that does the task is not an instance of the object (so that I can mock it), but the class definition is imported at the top of the document.

Solutions

Should I pass the MongooseUser class definition as a parameter inside the constructor?

Suppose I have this code inside the conversion method:

 let user = new this.MongooseUser({}) 

Do you have an idea to abstract the behavior of the mongoose in the way data is displayed?

I do not want to use another module, this, in my opinion, is the most advanced with NodeJS ...

+7
ecmascript-6 unit-testing mongodb mongoose
source share
1 answer

I am not familiar with import (and EMCASCRIPT-6 ) syntax, although you say you use node.js , so I recommend using proxquire . The idea is that the package allows you to require an external package while meeting the requirements that the package will use. So in your case, you can do something like:

 proxyquire('../my/class/that/uses/mongoose', { mongoose: MyTestMongooseImplementation }) 

So you can use your own mongoose implementation while still using MongooseUser , as you defined in your package. Alternatively, you can simply override the MongooseUser class (the path relative to the file whose requirements you are knocking:

 proxyquire('/path/to/UserMongooseRepository', { '../../auth/mongooseModel/MongooseUser': MyTestMongooseUser }) 

Documentation: https://www.npmjs.com/package/proxyquire

0
source share

All Articles