How should I be testing ES2015 classes? - javascript

My experience is with statically typed languages, and I must admit that I feel lost when trying to achieve the same with dynamic languages. One of the things that I would like to avoid, is apply concepts that don't make sense in this context. Please, assume that this class belongs to my project and that we want to test it with Jasmine:
class MyEs6Class {
constructor(
collaborator1 = new MyCollaborator(),
factory = new MyFactory()) {
this.collaborator1 = collaborator1;
this.factory = factory;
}
method() {
// Code
}
}
I'm providing default instances of the objects in the constructor because that allows me to mock them when testing. I'm trying to use inversion of control in the same way that I would use with, let's say C#, but using the dynamic features of the language to avoid a Dependency Injection container. These two dependencies are required by the class, so from the structural point of view, I think is very clear that they must be provided using the constructor.
Also, I'm using the concept of a factory only because while the class is 'alive' can require new objects from the factory several times.
From the point of view of ES6 classes, I know that there is no difference between private and public (https://stackoverflow.com/a/27853642/185027), so I could have the logic handled by the factory in a private method, but depend on him testing seems just wrong. On the other side having something called factory just because I need to fake the objects that returns seems weird, and maybe is screaming my lack of knowledge.
What is the proper way to mock collaborators in this context?.
Is it silly to have the concept of a factory only because I need to mock the object that returns?.
What would be a maintainable and elegant way of isolating the subject under test in Javascript/ES6?. Any interesting public codebase that I can study?.

Related

inversify help required and why do we need it?

Can you recommend any great learning resources on inversify in typescript?
I have looked at http://inversify.io/ and have followed the example but am not grasping how it really works or why I need it.
A great video learning resource would be great or a simple easy beginner example.
Thanks for the help.
The idea of Inversion Of Control, aka dependency injection is that a class hands over control (read: responsibility) for instantiating dependent instances that the class needs to the container that will provide them with these instances instead.
So you would not do something like:
public constructor() {
this._katana = new Katana();
this._shuriken = new Shuriken();
}
I am not going to give a full example, because I would basically be copy-pasting the code that they clearly share on their website in the section 'The Basics'.
They give an example of constructor injection:
public constructor(
#inject(TYPES.Weapon) katana: Weapon,
#inject(TYPES.ThrowableWeapon) shuriken: ThrowableWeapon
) {
this._katana = katana;
this._shuriken = shuriken;
}
This is specifically useful for:
Testing, since the dependent object can be mocked and injected
Injecting dependent objects based on variable parameters.
For example, depending on environment you may want to inject a different configuration object with different values. This is just one example.
Constructor injection is usually preferred over property injection, as the library also seems to support this.
Note that what is injected is an interface, not a concrete class type.
So the class just declares that it needs an object of type Weapon / ThrowableWeapon.
The concrete binding happens in inversify.config.ts:
container.bind<Weapon>(TYPES.Weapon).to(Katana)
So the reason why this is useful is that you have the ability to provide concrete classes at runtime. You don't need to pre-define (hardcode) them in the class.

Abstract Classes v Singletons v Public-statics in Typescript

I've moved from a functional style of coding Javascript to class based Typescript for work. The are cases where I need only one instance/place for some functionality so sometimes I have gone for an abstract class whilst at other times I have opted for a singleton. My reason for choosing one over the other are a little arbitrary and fuzzy and my colleagues suggestions have sounded fuzzy also.
When would you use an abstract class verses and singleton class verses a regular class with public static methods and properties. Actual examples and use case to help in deciding when to use which would be great.
Currently abstract and singletons seem pretty similar to me when it comes to the case of creating something where there is only one but my reason for picking the latter up till now has simply been that I can do this.property with a singlton whereas within an abstract it seems correct to use only abstractClassName.property which is more verbose. Both seem a good option for centralising state such as a common list of timers item items[]
Don't use a class if you don't plan to instantiate it.
Don't use an abstract class if you don't plan to extend it.
A plain object is a better fit for a collection of static methods. In Typescript, you'd probably use a namespace or module of functions.

Is a factory of classes a valid javascript pattern?

Some time ago I learnt a lot of design-patters, specially creational ones.
After some time, I found myself using a patter that I though existed, but when I tried to search about it I didn't found any reference. Basically it is a small modification of a factory which takes advantages of the closures to resolve dependencies of a class. Actually, it is a factory of classes. Let's me illustrate this with a bit of code:
function Factory(depA,depB){
function MyClass(something){
this.something = something;
}
MyClass.prototype.methodA(){ // use depA}
MyClass.prototype.methodB(){ // use depB}
return MyClass
}
Let's assume that depA is a database and depB is a logger. Then you can use the factory like this
var BindedClass = Factory(database,logger);
var instance = new BindedClass(something);
I find this patter very useful for injecting common dependencies, without loosing the control of how the class is actually instantiated.
However, this has some problems. For example, one of the things that made me realize that this is not so common is that JSDoc does not have support at all for this kind of pattern.
Is it a bad pattern? I can't find any disadvantage on it apart from less modularization and non-working documentation tools.
Yes, it's a totally accepted pattern. However we rarely call it a "factory", more common is just "module" - in this case with dependency injection. Many module systems like AMD use this pattern.
You should however ensure that the factory produces a singleton - i.e. Factory should not be called multiple times and create multiple similar classes.

typescript & angular design - alternative way of passing dependencies

Hello TypeScript/Angularists!
TL;DR
Can I pass angular dependencies to a TypeScript module/class, so that those dependencies DON'T become attributes of class objects - instead, they are available through scope function parameters?
I know the recommended way of declaring things in angular/typescript is to create a TS class inside a TS module and release it as an angular service, because:
it can't be a factory (see this)
it's good to have modules
a class (comparing to a plain function) might be used to check compile-time types in typescript
An example of such approach is below:
/// <reference path="../../project.d.ts" />
module project.core.services {
export class UiRoutes {
static $inject = ['$state'];
constructor(private $state: angular.ui.IStateService) {
}
public reloadCurrentView(): void {
this.$state.go(this.$state.current.name, this.$state.params, {
reload: true
});
}
}
}
project.core.CoreModule.service('UiRoutes', project.core.services.UiRoutes);
Anyway, there is one great problem with that approach and that is - I'm forced to pass all angular dependencies into class constructor to make them object attributes (available everywhere, not encapsulated - because if the object is accessible then all it's attributes are accessible).
As an alternative, there is Backbone.js + Require.js example:
define(['jquery', 'use!backbone','models/model'], function($, Backbone, Model){
View = Backbone.View.extend({
//...
});
return new View();
});
where, as you can see, jquery, backbone and some internal stuff is available, but it's not saved as an object attribute - it's available through scope. This is purely natural JavaScript way of doing things - passing things through scope function parameters. In this situation, you can encapsulate more things and your code becomes less verbose. And, mainly, it's good to have a choice rather than to be forced to follow the only right rule.
Now I know that backbone is different than angular and, moreover, DI is totally different than require.js, blah blah blah.
What I want is a an example (or just a design) that allow me to specify all angular dependencies and make them accessible for a TypeScript module/class but not to make them attributes of class objects. This is possible with pure AngularJS (without TypeScript) afterall, so it might be possible along with TypeScript.
PS I'll happily provide better description of the problem, if it's not clear (comments, please). Buit I'm not really interested in answers like "it's not what you want, but it works for me, try this" :) if the answer is "no, that's not possible", than I'd appreciate a proof and/or reasons why.
because if the object is accessible then all it's attributes are accessible
This may be true from a runtime perspective, but the runtime perspective is not the only one that matters. If you're using TypeScript and you mark the injected services as private, then no one is accessing these things unless they're being actively malicious. And odds are extremely good that your code is already not resilient to malicious actors inside its own runtime environment (trivially, someone who wanted to screw with your app could inject in any Angular service and overwrite its properties with their own).
So in that regard, the best thing to do is to not care about what things happen to be on a object somewhere versus in a closure somewhere.
Now I know that backbone is different than angular and, moreover, DI is totally different than require.js, blah blah blah.
To expand on "blah blah blah", a relevant difference here is that your requirejs module is effectively a singleton, whereas your Angular classes usually aren't (most of them are probably controllers).
We need to go back to the object vs closure difference to understand why that matters. If you're going to have closure privacy over your injected services (because compile-time privacy wasn't good enough for whatever reason), it follows that every instance of your object is going to need its own set of subclosures to be able to access those closed-over values.
Duplicating your function closures for every single instance of an object incurs a large performance penalty when there are many instances of the object. It's more allocations, more memory pressure, more time spent cleaning up things in the GC, more time spent marking or sweeping or refcounting in the GC, less locality of reference, less efficient JIT, and so on. This is why TypeScript and other languages don't give you ready-made footguns for making closure-based classes.
Now you're saying "But my service is a singleton!" and you're right. Singletons can be written as a closure like this:
module project.core.services {
export function UiRoutes($state: angular.ui.IStateService) {
function go() {
$state.go(/* etc*/);
}
function other() { }
function foo() { }
return {
go,
other,
foo
}
}
}

Dependency Injection and Interfaces in Node

Coming from a C# background, I used interfaces to base my mock objects off of. I created custom mock objects myself and created the mock implementation off a C# interface.
How do you do something like this in JS or node? Create an interface that you can "mock" off of and also the interface would serve for the real class that would also be able to implement that interface? Does this even make sense in JS or or the Node World?
For example in Java, same deal, define an interface with method stubs and use that as the basis to create real class or mock class off of.
Unfortunately you're not going to find the standard interface as a part of JavaScript. I've never used C#, but I've used Java, and correct me if I'm wrong, but it looks like you're talking about creating interfaces and overriding methods for both mock testing purposes, as well as being able to implement those interfaces in other classes.
Because this isn't a standard JavaScript feature, I think you'll find that there are going to be a lot of very broad answers here. However, to get an idea of how some popular libraries implement this, I might suggest looking at how AngularJS looks at mock testing (there are many resources online, just Google it. As a starting point, look at how they use the ngMock module with Karma and Jasmine.)
Also, because of JavaScript's very flexible nature, you'll find that you can override any sort of "class method" (that is, any function object that is a member of another object, whether that be a new'ed "class" or a plain object) by simply re-implementing it wherever you need to... there's no special syntax for it. To understand where and how you would accomplish this, I'd suggest looking from the ground up at how JavaScript using prototypal/prototypical inheritance. A starting point might be considering an example like this:
function Cat(config) {
if(typeof config !== 'undefined') {
this.meow = config.meow; // where config can possibly implement certain mock methods
}
}
Cat.prototype = {
this.meow = function() {
// the meow that you want to use as part of your "production" code
};
};
var config = {};
config.meow = function() {
// some mock "meow" stuff
};
var testCat = new Cat(config); // this one will use the mock "Cat#meow"
var realCat = new Cat(); // this one will use the prototype "Cat#meow"
In the above example, because of how JavaScript looks up the prototype chain, if it sees an implementation in the class itself, it'll stop there and use that method (thus, you've "overridden" the prototype method). However, in that example, if you don't pass in a config, then it'll look all the way up to the prototype for the Cat#meow method, and use that one.
TL;DR: there's not one good way to implement JavaScript interfaces, especially ones that double as mocks (there's not even a best way to implement dependency injection... that's also a foreign concept to JavaScript itself, even though many libraries do successfully implement it for cetain use-cases.)

Categories