How to stub a private method of a class written in typescript using sinon - node.js

I am writing unit tests for a public method which is, in turn, calling a private method of the class written in typescript (Node JS).
Sample Code
class A {
constructor() {
}
public method1() {
if(this.method2()) {
// Do something
} else {
// Do something else
}
}
private method2() {
return true;
}
}
Now to test method1() I need to stub method2() which is a private method.
here what I am trying :
sinon.stub(A.prototype, "method2");
Typescript is throwing the error :
Argument of type '"method2"' is not assignable to parameter of type '"method1"'
Any help would be appreciated.
Thank You

The problem is that the definition for sinon uses the following definition for the stub function :
interface SinonStubStatic { <T>(obj: T, method: keyof T): SinonStub; }
This means that the second parameter must be the name of a member (a public one) of the T type. This is probably a good restriction generally, but in this case it is a bit too restrictive.
You can get around it by casting to any:
sinon.stub(A.prototype, <any>"method2");

Sometimes when the complexity of code and tests is more significant I prefer to "externalize" private methods. You can do that, that either with a (partial) class or a (partial) interface.
it('private methods test', async () => {
// original class
class A{
public method1():string{
if(this.method2()) {
// Do something
return "true";
} else {
// Do something else
return "false";
}
}
// with private method
private method2():boolean{
return true;
}
}
// interface that makes the private method public
interface IAExternalized{
method2():boolean;
}
// class that makes the private method public
class APrivate implements IAExternalized{
// with public method
method2():boolean{
return true;
};
}
// test before mocking
let test:A = new A();
let result:string = test.method1();
result.should.be.equal("true");
// let's mock the private method, but with typechecking available
let stubMethod2:sinon.SinonStub = sinon.stub(<IAExternalized><unknown>(A.prototype), "method2").returns(false);
result = test.method1();
result.should.not.be.equal("true");
result.should.be.equal("false");
// access private method of an object through public-interface
let testPrivate:IAExternalized = <IAExternalized><unknown>test;
let result2:boolean = testPrivate.method2();
result2.should.not.be.equal(true);
result2.should.be.equal(false);
});
NOTE: If you control the code you are testing, you do not need to double code, prone to mistakes, but you can make your class implement the interface. To convert standard (without private) interface into "externalized" you can extend it with public methods.
export interface IAExternalized extends IAPrivate {
method2():boolean
};

Related

How to return a class instance with an expression macro?

Driver code
//---------------- Main.hx ------------------------------------------------------------------
import core.reflection.ReflectionTools;
import core.SomeClass;
class Main{
public static function main(){
var s = new SomeClass();
ReflectionTools.info(s);
}
}
The macro
//---------------- ReflectionTools.hx -----------------------------------------------------
class RelectionTools {
public static macro function info(obj:Expr):Expr{
var pos = Context.currentPos();
var block = [];
var result:Dynamic;
var type:Type=Context.typeof(obj);
result=(switch(type){
case TInst(t, params):new RelectionClass(t, params);
case TEnum(t, params):new ReflectionEnum(t, params);
case TDynamic(t):new ReflectionDynamic(t);
case TFun(args, ret):new ReflectionFunction(args, ret);
case TMono(t):new ReflectionMonomorph(t);
case TLazy(f):new ReflectionLazy(f);
case TAbstract(t, params):new ReflectionAbstract(t, params);
case TType(t, params):new ReflectionTypeDefinition(t, params);
case TAnonymous(a):new ReflectionAnonymousStructure(a);
});
return $v{result};
}
}
Haxe Compiler:
Expected Expr but got core.reflection.RelectionClass (see dump/decoding_error.txt for details)
It is not a build macro (which allows returning class instances) but it is an expression macro. The best way to mimic class functionality is with abstracts.
/* Solution Description
1. a custom Json abstract with underlying type {} and with implicit
casts to underlying type. See Json.hx
2. abstracts which reflect possible Type enums with underlying custom
Json abstract and forwards. See example ReflectionPrimitive.hx
and mimic inheritance by underlying types as superclass
see example ReflectionFunction.hx
3. uses same instantiation code as original class instantiation
but now they are abstracts (see PROBLEM(The macro). Solved! */
Step 1.a custom Json abstract with underlying type {} and with implicit casts to
underlying type.
// ---------------- Json.hx ----------------------------------------------
package core.ds.json;
import haxe.Serializer;
import haxe.Unserializer;
import haxe.Json as J;
abstract Json({}) from ({}) to ({}) {
public inline function new(?data:{}){
this=data;
if(this==null){
this={};
}
}
#:arrayAccess
public inline function get(key:String):Dynamic{
if(exists(key)){
return Reflect.field(this,key);
}
return null;
}
#:arrayAccess
public inline function set(key:String, value:Dynamic):Dynamic{
Reflect.setField(this, key, value);
return value;
}
public inline function isEmpty(key:String):Bool{
return !isSet(key) || (exists(key) && ( get(key)=="" || get(key)==''|| get(key)==null || get(key)==0 ));
}
public inline function isSet(key:String):Bool{
return exists(key) && get(key)!=null;
}
public inline function exists(key:String):Bool {
return Reflect.hasField(this, key);
}
#:to
public inline function toMap():Map<String, Dynamic>{
var result:Map<String, Dynamic>=new Map<String, Dynamic>();
var fields:Array<String>=Reflect.fields(this);
for (f in fields){
result.set(f, Reflect.field(this, f));
}
return result;
}
#:to
public inline function toJsonString():String{
return J.stringify(this,null," ");
}
public inline function values():Array<Dynamic>{
var result:Array<Dynamic>=[];
var keys:Array<String>=keys();
for(k in keys){
result.push(Reflect.field(this,k));
}
return result;
}
public inline function keys():Array<String>{
return Reflect.fields(this);
}
public inline function clone():Json{
return Unserializer.run(Serializer.run(this));
}
public var length(get,never):Int;
private inline function get_length():Int{
return keys().length;
}
public inline function keyValueIterator():KeyValueIterator<String, Dynamic>{
return toMap().keyValueIterator();
}
#:from
public static function fromJsonString(json:String):Json{
return J.parse(json);
}
#:from
public static function fromMap(map:Map<String, Dynamic>):Json{
var result={};
for (k=>v in map){
Reflect.setField(result, k, v);
}
return result;
}
}
Step 2. abstracts which reflect possible Type enums with underlying custom Json abstract and forwards. See example ReflectionPrimitive.hx and mimic inheritance by underlying types as superclass see example ReflectionFunction.hx
//---------------- ReflectionPrimitive.hx ----------------------------------------------
#:forward()
abstract ReflectionPrimitive(core.ds.json.Json) from core.ds.json.Json to core.ds.json.Json{
public inline function new(nameType:String){
this=new core.ds.json.Json({data:new core.ds.json.Json(), info:new core.ds.json.Json({nameType:nameType})});
}
public var data(get, set):core.ds.json.Json;
public var info(get, set):core.ds.json.Json;
private function get_data():core.ds.json.Json {
return this["data"];
}
private function set_data(value:core.ds.json.Json):core.ds.json.Json {
this["data"]=value;
return this;
}
private function get_info():core.ds.json.Json {
return this["info"];
}
private function set_info(value:core.ds.json.Json):core.ds.json.Json {
this["info"]=value;
return this;
}
}
Mimmicking inheritance
//---------------- ReflectionFunction.hx ----------------------------------------------
#:forward(data, info, get, isEmpty, isSet, exists, toMap, toJsonString, values, keys, clone, length, keyValueIterator, fromJsonString, fromMap)
abstract ReflectionFunction(ReflectionPrimitive) from ReflectionPrimitive to ReflectionPrimitive{
public inline function new(args:Array<{t:Type, opt:Bool, name:String}>, ret:Type){
this=new ReflectionPrimitive(NameType.FUNCTION);
var newArgs=new Array<core.ds.json.Json>();
for(a in args){
newArgs.push(new core.ds.json.Json(a));
}
this.data=this.data.set("args",newArgs).set("ret", ret);
}
public var args(get, never):Array<core.ds.json.Json>;
public var ret(get,never):Type;
private function get_args():Array<core.ds.json.Json>{
return this.data.get("args");
}
private function get_ret():Type{
return this.data.get("ret");
}
}
Leave the macro untouched it will work now.
Macro is a compile time feature, not runtime feature, you can't return class instance. Instead, you have to return expression which creates a new instance (I don't have your classes, so I use here my class)
var type=Context.typeof(obj);
return (switch(type){
case TInst(t, params):macro new MyClass();//RelectionClass(t, params);
case TEnum(t, params):macro new MyClass();//ReflectionEnum(t, params);
case TDynamic(t):macro new MyClass();//ReflectionDynamic(t);
case TFun(args, ret):macro new MyClass();//ReflectionFunction(args, ret);
case TMono(t):macro new MyClass();//ReflectionMonomorph(t);
case TLazy(f):macro new MyClass();//ReflectionLazy(f);
case TAbstract(t, params):macro new MyClass();//ReflectionAbstract(t, params);
case TType(t, params):macro new MyClass();//ReflectionTypeDefinition(t, params);
case TAnonymous(a):macro new MyClass();//ReflectionAnonymousStructure(a);
});
return macro null;

How to extend a class in typescript

My service is designed in nodejs.
Below is my scenario
i have two controllers, one will be extending the other. there is a static function in both the controllers where in a static variable will be assigned some value.
depending on the condition of the data, im trying the make a call to the respective controller so that the static variable gets a appropriate assigned value.
Note:
The below code is just a snippet to explain the scenario and not the actual code of the application. But the order / calling / controller structure of this code snippet is exactly same. Also the listOfDept variable will be having separate business logic in the checkStart function of firstController and secondController.
// firstController.ts
firstController implements IFirstController {
private static listOfDept: string[];
static checkStart(){
firstController.listOfDept = // my logic to fill this object
}
constructor (){}
}
getRelevantData(next: (error: string, response: any) => void): void {
var myObject = firstController.listOfDept;
this.myRepository.uniqueData(myObject, next);
}
}
firstController.checkStart();
export = firstController;
//ifirstController.ts
interface IFirstController {
getRelevantData(next: (error: string, response: any) => void): void;
}
// secondController.ts
secondController extends firstController implements iSecondController {
private static listOfDept: string[];
static checkStart(){
firstController.listOfDept = ["Computer Science"];
}
constructor (){
super();
}
}
secondController.checkStart();
export = secondController;
//isecondController.ts
interface ISecondController implements ifirstController{}
//Controller calling the getRelevantData function
//middlewareController
middlewareController implements IMiddlewareController {
constructor(private firstController: IFirstController, private secondController: ISecondController) {
}
getDepData(data: any, next: (error: string, response: any) => void): void {
if(data.url = "fromParent") {
// im expecting this to make a call to checkStart() of firstController
this.firstController.getRelevantData();
} else {
// im expecting this to make a call to checkStart() of secondController
this.secondController.getRelevantData();
}
}
}
Problem faced with the above code
No matter which way the getRelevantData function is getting called, im always getting the value of listOfDept as computer science. It is never going in the checkStart function of first controller.
In general I would discourage using static methods for this kind of initialization and instead inject the required data into constructors or create factory methods for creating object with necessary data.
But, if you do want to use static properties, the problem is that you need to refer to the right parent class in the getRelevantData implementation. The class that constructed the instance can be accessed through constructor property. TypeScript does not process this scenario well, so you have to make a type cast:
// firstController.ts
class firstController implements IFirstController {
// Need to be `protected` to be accessible from subclass
protected static listOfDept: string[];
static checkStart(){
firstController.listOfDept; // my logic to fill this object
}
constructor (){}
getRelevantData(next: (error: string, response: any) => void): void {
// You need to refer to the constructor
let Class = this.constructor as typeof firstController;
var myObject = Class.listOfDept;
// the rest
}
}
firstController.checkStart();
//ifirstController.ts
interface IFirstController {
getRelevantData(next: (error: string, response: any) => void): void;
}
// secondController.ts
class secondController extends firstController implements ISecondController {
// No `listOfDept` definition here
static checkStart(){
secondController.listOfDept = ["Computer Science"];
}
constructor (){
super();
}
}
secondController.checkStart();

How to use class functions in another class?

How can i use class instance in another class like a pointer in C++ to class instance functions?
Example:
class A {
constructor()
{
this.block = [];
}
method()
{
return this.blocks.length;
}
}
another class:
class B {
constructor(instance)
{
this.instance = instance;
}
method()
{
this.instance.method(); // here i'm getting cannot get length of undefined
}
}
If i'm trying to to like that i'm getting problems to call it
You can try this. Here, when creating B class's instance I give into it an A class's instance as argument. Then inside B we can call A instance's methods, and access its properties.
Also, as #ViaTech posted you can use static methods to access them without needing to initialize an object of the class. That is what static methods is. Refer Static Methods
class B {
constructor(instance)
{
this.instance = instance;
}
method()
{
this.instance.method();
}
}
class A {
constructor()
{
}
method()
{
console.log("A's method");
}
}
var a = new A();
var b = new B(a);
b.method(); // A's method
You can easily do this in JS by calling a static method like so:
class A {
static write(){ //static method
console.log("Called write from A");
}
}
class B {
doIt(){
A.write();
}
}
let b = new B();
b.doIt();
Option 2, you instantiate the class in the constructor of the other like so:
class A {
write(){
console.log("Non-static write() called from class A");
}
}
class B {
constructor() {
this.a = new A();
}
doIt(){
this.a.write();
}
}
let b = new B();
b.doIt();
There are a few ways:
I accidentally switched between PHP and Javascript, but the principles are the same for both)
Use static functions:
Normally, you have a this in the class. Say you have this code:
class Car {
let color;
public function setColor(newColor){ this.color = newColor;}
}
let car = new Car();
car->setColor('green')`
The setColor function's this refers to that car. You can make let anotherCar = new Car(), then when you do anotherCar->setColor('red') you only change that car, not the first one. Simplistic: You can create multiple instances.
If you do not need that, but need the class once, you can make it static. A simple way to explain would be "you have a collection of seperate functions, just put into a wrapping class (which doesn't do a lot really)". For instance, you might have some sanatizing methods:
class Sanitize {
static function makeHtmlSave(input){
return doYourMagicHere(input);
}
static function removeXssCode(input){
return doMoreMagicHere(input);
}
}
This way, you can reuse it multiple times. If you want to use it, you do Sanitize::makeHtmlSave(someCode) where you need it. There isn't a Sanitize thing, it's just a wrapper to access the frunctions inside it.
Use extend:
You can extend a class. Say you have a generic class Vehicle, which has some properties (eg a motor, numberWeels, color) and you can extend that with more specific classes:
class Vehicle {
let color;
public function setColor(newColor){ this.color = newColor}
}
class Car extends Vehicle {
let hasAirco = false;
public function hasAirco(newValue){ this.hasAirco = newValue};
}
If you do let car = new Car(), you get a Car object, that extends/enlarges/complements the Vehicle class, so you can use both its (public) functions. Internally, Car can use the functions of Vehicle too.
Just pass it
class One {
// some stuff
}
class Two{
let otherObject;
construct(givenObject){
this.otherObject = givenObject;
}
}
You can now do this let a = new One(); let b = new Two(a);. You can not use the functions of One inside Two, but you can still use a->doSomething(). This solution feels like the easiest, but it almost never is. Classes/objects are tricky stuff, but I've rarely uses this solutions. There are use cases, but often it's a bad smell indicator.

Haxe: Native Interface properties implementable?

I've got this compiletime errors when I make some class implement an interface with properties that have been fromerly defined in some native sub class, like openfl.display.Sprite. It occurs when I'm targeting flash, not js.
Field get_someValue needed by SomeInterface is missing
Field set_someValue needed by SomeInterface is missing
Field someValue has different property access than in SomeInterface (var should be (get,set))
In contrast, there's no problem with interface definitions of 'native' methods or 'non-native' properties. Those work.
Do I have to avoid that (not so typical) use of interfaces with haxe and rewrite my code? Or is there any way to bypass this problem?
Thanks in advance.
Example:
class NativePropertyInterfaceImplTest
{
public function new()
{
var spr:FooSprite = new FooSprite();
spr.visible = !spr.visible;
}
}
class FooSprite extends Sprite implements IFoo
{
public function new()
{
super();
}
}
interface IFoo
{
public var visible (get, set):Bool; // Cannot use this ):
}
TL;DR
You need to use a slightly different signature on the Flash target:
interface IFoo
{
#if flash
public var visible:Bool;
#else
public var visible (get, set):Bool;
#end
}
Additional Information
Haxe get and set imply that get_property():T and set_property(value:T):T both exist. OpenFL uses this syntax for many properties, including displayObject.visible.
Core ActionScript VM classes (such as Sprite) don't use Haxe get/set, but are native properties. This is why they look different.
Overriding Core Properties
If you ever need to override core properties like this, here is an example of how you would do so for both Flash and other targets on OpenFL:
class CustomSprite extends Sprite {
private var _visible:Bool = true;
public function new () {
super ();
}
#if flash
#:getter(visible) private function get_visible ():Bool { return _visible; }
#:setter(visible) private function set_visible (value:Bool):Void { _visible = value; }
#else
private override function get_visible ():Bool { return _visible; }
private override function set_visible (value:Bool):Bool { return _visible = value; }
#end
}
Overriding Custom Properties
This is not needed for custom properties, which are the same on all platforms:
class BaseClass {
public var name (default, set):String;
public function new () {
}
private function set_name (value:String) {
return this.name = value;
}
}
class SuperClass {
public function new () {
super ();
}
private override function set_name (value:String):String {
return this.name = value + " Q. Public";
}
}
Need to provide the method signatures in an Interface. Currently its just a property declaration.
The error message is saying it all.
Field get_someValue needed by SomeInterface is missing
Field set_someValue needed by SomeInterface is missing
Hopefully that helps.

ViewHelper newable/injectable dilemma

I'm trying to design an application following Misko Heverys insights. It's an interesting experiment and a challenge. Currently I'm struggling with my ViewHelper implementation.
The ViewHelper decouples the model from the view. In my implementation it wraps the model and provides the API for the view to use. I'm using PHP, but I hope the implementation is readable for everyone:
class PostViewHelper {
private $postModel;
public function __construct(PostModel $postModel) {
$this->postModel = $postModel;
}
public function title() {
return $this->postModel->getTitle();
}
}
In my template (view) file this could be called like this:
<h1><?php echo $this->post->title(); ?></h1>
So far so good. The problem I have is when I want to attach a filter to the ViewHelpers. I want to have plugins that filter the output of the title() call. The method would become like this:
public function title() {
return $this->filter($this->postModel->getTitle());
}
I need to get observers in there, or an EventHandler, or whatever service (in what I see as a newable, so it needs to be passed in through the stack). How can I do this following the principles of Misko Hevery? I know how I can do this without it. I'm interested in how for I can take it and currently I don't see a solution. ViewHelper could be an injectable too, but then getting the model in there is the problem.
I didn't find the blog post you referenced very interesting or insightful.
What you are describing seems more like a Decorator than anything to do with dependency injection. Dependency injection is how you construct your object graphs, not their state once constructed.
That said, I'd suggest taking your Decorator pattern and running with it.
interface PostInterface
{
public function title();
}
class PostModel implements PostInterface
{
public function title()
{
return $this->title;
}
}
class PostViewHelper implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->post->title();
}
}
class PostFilter implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->filter($this->post->title());
}
protected function filter($str)
{
return "FILTERED:$str";
}
}
You'd simply use whatever DI framework you have to build this object graph like so:
$post = new PostFilter(new PostViewHelper($model)));
I often use this approach when building complex nested objects.
One problem you might run into is defining "too many" functions in your PostInterface. It can be a pain to have to implement these in every decorator class. I take advantage of the PHP magic functions to get around this.
interface PostInterface
{
/**
* Minimal interface. This is the accessor
* for the unique ID of this Post.
*/
public function getId();
}
class SomeDecoratedPost implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->_post = $post;
}
public function getId()
{
return $this->_post->getId();
}
/**
* The following magic functions proxy all
* calls back to the decorated Post
*/
public function __call($name, $arguments)
{
return call_user_func_array(array($this->_post, $name), $arguments);
}
public function __get($name)
{
return $this->_post->get($name);
}
public function __set($name, $value)
{
$this->_post->__set($name, $value);
}
public function __isset($name)
{
return $this->_post->__isset($name);
}
public function __unset($name)
{
$this->_post->__unset($name);
}
}
With this type of decorator in use, I can selectively override whatever method I need to provide the decorated functionality. Anything I don't override is passed back to the underlying object. Multiple decorations can occur all while maintaining the interface of the underlying object.

Resources