Coder Social home page Coder Social logo

typemoq's People

Contributors

florinn avatar guscastro avatar jesperronn avatar mpodlasin avatar rkostrzewski avatar the-vk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

typemoq's Issues

Reset mocks?

I have a "clock" module that provides a singleton instance, to use instead of calling "new Date()" directly. To unit test other modules that make use of the clock module, I have to mock out the singleton instance, and mock its "now()" method.

This means each invocation of "clock.now()" needs a different value. To achieve, this, for each invocation, I need to create a mock of the Clock class and inject it into the system under test (using mockery). This is not ideal; I'd much rather create a placeholder mock, inject it once, and apply a different setup within each unit test.

Is there some way to reset mocks? Or, at least, to apply "setup()" calls without falling into the "record/replay" functionality?

Node dependency prevents using typemoq with react native

I'm working on a react native project with typescript, and was hoping to use typemoq with it. Unfortunately typemoq depends on @types/node, which conflicts with @types/react-native.

What is it from node that typemoq requires? Would it be possible to duplicate those types rather than pull in the node type definition?

Proxy.isProxy() throws an error when trying to clone an object with a null value (via StaticMock.cloneDeep())

The proxy.isProxy() function doesn't check for null before checking for the __id string in an object (when calling .Mock.ofInstance).

Here's a rough replication of the issue in raw JS:

function cloneDeep(target) {
        var copy = target;
        if (!_.isFunction(target)) {
            var func = function (x) {
                var value;
                if (isProxy(x))
                    return x;
            };
            copy = _.cloneDeepWith(target, func);
        }
        return copy;
}

function isProxy(obj) {
        console.log(obj);
        if (!_.isUndefined(obj) &&
            !_.isUndefined(obj['__id']) && obj['__id'] === 'test')
            return true;
        else
            return false;
}

cloneDeep({
    a: {
        b: {
            c: null
        }
    }
});

and here's the backtrace I get (against 1.0.1):

TypeError: Cannot read property '___id' of null
      
      at Function.Proxy.isProxy (node_modules/typemoq/dist/typemoq.js:530:31)
      at func (node_modules/typemoq/dist/typemoq.js:1208:29)
      at baseClone (node_modules/lodash/lodash.js:2667:27)
      at node_modules/lodash/lodash.js:2721:34
      at arrayEach (node_modules/lodash/lodash.js:537:11)
      at baseClone (node_modules/lodash/lodash.js:2715:7)
      at Function.cloneDeepWith (node_modules/lodash/lodash.js:11120:14)
      at Function.StaticMock.cloneDeep (node_modules/typemoq/dist/typemoq.js:1211:22)
      at Function.StaticMock.ofInstance (node_modules/typemoq/dist/typemoq.js:1190:37)
      at Function.MockApi.ofInstance (node_modules/typemoq/dist/typemoq.js:1274:31)

I suspect the fix would be to replace the _.isUndefined call with something that only proceeds if obj is a valid non-null object.

Dynamic Mock uses Proxy features that cannot be fulfilled in a ES5 engine

The Dynamic mocks should be somehow satisfied without using the constructor and the special Proxy features .

In the following example it is impossible to create a mock for the class A:

Given that

class A {
  constructor(b : B){
   b.foo();
  }
}

class B {
  foo(){
   console.log('foo')
  }
}

The constructor cannot be used in a call like this one :

const AMock: TypeMoq.IMock<A> = TypeMoq.Mock.ofType<A>(A);

Because A constructor calls B and when A is initialized B is null.

Or like this:

const AMock: TypeMoq.IMock<A> = TypeMoq.Mock.ofType<A>();

Because TypeMoq.Mock.ofType<A>() relies on a ES6 Proxy feature that cannot be "pollyfilled".

testing observable catch

Hi probably it's not issue of typemoq but maybe you can help me, and it might be a good example for this lib.

I cannot find a way to test rxjs catch...

Test code:

  let mockHttp:TypeMoq.Mock<Http>;
  let mockErrorHandler:TypeMoq.Mock<ErrorHandler>;
  let httpJSONService:HttpJSONService;

  beforeEach(() => {
    mockHttp = TypeMoq.Mock.ofType(Http);
    mockErrorHandler = TypeMoq.Mock.ofType(ErrorHandler);
    httpJSONService = new HttpJSONService(mockHttp.object, mockErrorHandler.object);
  });

  it('logs error to console on failure', () => {
    const error:any = 'sample-error';
    mockHttp
      .setup(x => x.delete(TypeMoq.It.isAny()))
      .returns(x => Observable.throw(new Error(error))); // does not throw an error, does not trigger catch
      // .throws(new Error(error));  // <-- throws error, does not trigger catch

    httpJSONService.delete(TypeMoq.It.isAny());

    mockErrorHandler.verify(x => x.logToConsole(error), TypeMoq.Times.once());
  });

Code:

 constructor(private http:Http,
             private errorHandler:ErrorHandler) {
  }

  public delete<T>(url:string):Observable<T> {
    return this.http.delete(url)
      .catch((err) => this.errorHandler.logToConsole<T>(err));
  }

Problem with global mocking - karma - phantomjs - jspm

Hi,

first of all thanks for this great promising project!

I wanted to use it but I found some problem maybe you can help me.
When I run my test with globalmock i get

PhantomJS 2.1.1 (Mac OS X 0.0.0)
Property description must be an object.
defineProperty@[native code]
forEach
with

there is only one test with only one it with code copied from your tests.
Error occurs at this line

here is my example
You can just clone it and then:
npm install
npm test

Support ECMAScript 6

I am using this library in my project but it does not seem to work with nodejs v5.8.0 (ES6).

interface IFoo {
    hello(): string
}

class Foo  {
    constructor(public name: string) { }

    hello(): string {
        return "hi";
    }
}

var mock : Mock<IFoo> = Mock.ofType(Foo)

executing this code gives a runtime error Class constructors cannot be invoked without 'new'

is this a known issue?

Return callback on properties?

Im trying to attach a return callback on a mocked property, but gets a InvalidSetupExpression Exception.

Is this a bug/missing feature or am i using the library wrong?

class z {
x: string;
}
let w = typemoq.Mock.ofType(z);
w.setup(m => m.x).returns(() => {
return "y";
});

Reset works incorrectly

it('test', () => {
    const mock = Mock.ofInstance<() => void>(() => {});
    const obj = mock.object;
    mock.reset();
    obj();
    mock.verify(f => f(), Times.once());
});

Feature Request: Multiple setups for same property

Hi,

in many cases I want to mock an objects default behavior and have a specified behavior for a few tests.

E.g. I want a Service to always return a resolving promise so I can test the program flow. I am doing this by using setup() in Mocha's beforeEach()-hook.
When I now want to test the behavior when the Serve rejects the returned promise, I cannot simply use a second setup() call to override the first one.

See this pen as an example.

Being able to override setups would greatly improve the convenience of writing tests for me.

Invalid match object

it.only('test', () => {
    const mock = Mock.ofInstance<(x) => void>(() => {});
    const anObject = {};
    mock.setup(f => f(anObject)); // throws Invalid match object
});

Expected the setup above is a short form of

mock.setup(f => f(It.is(x => x === anObject)));

Setup on Dynamic Mock Not Matching

I am relatively new to Typescript and TypeMoq, so this may be something I'm doing wrong, but it looks correct to me.

I have the following classes defined (unnecessary stuff omitted for brevity):

const DEFAULT_TIMEOUT=2000;

class A {
 public doOperation<T>(
    op() => void,
    processData(data: string) => boolean,
    processError(err:string) => boolean,
    timeout: number = DEFAULT_TIMEOUT
  ) : Promise<T> {
    //does some stuff
  }
}

class B {
  constructor(private myA: A) {}
  public doSomething(): Promise<void> {
    return this.myA.doOperation<void>(
      () => console.log('doing it'),
      (x, y) => true,
      (x, y) => true
    );
  }
}

I am then trying to test B by mocking A. I have something like this:

describe('B', () => {
  let b: B;
  let a: TypeMoq.IMock<A>;

  beforeEach(() => {
    a = TypeMoq.Mock.ofType<A>(undefined, TypeMoq.MockBehavior.Strict);
    b = new B(a.object);
  });

  it('should do something', (done) =>{
    a.setup(x => x.doOperation<void>(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())
      .returns((op, processData, processError, timeout) => {
         //something meaningful
      }

      b.doSomething().then(() => done());
  });
});

My a.setup() does not match the call that is made inside B.doSomething() and I can't figure out why. I've tried a few things, all related to the parameter timeout which is assuming a default value in this case, none of which have worked:

  1. Removed the default value for timeout and explicitly passed a value in B.doSomething.
  2. Took a guess that maybe the default parameter caused the function to appear to be called 3 arguments instead of 4, so I tried removing the 4th TypeMoq.It.isAny() in the setup.

No matter what, I'm always getting a MockException: 'Function.doOperation'.

If it matters, I'm compiling to ES6, using node 7.7.1 and running tests with mocha.

Any help is appreciated.

Cannot install the npm package from the git repository

It would be very useful to install the latest package version from the git repository: npm install https://github.com/florinn/typemoq. It doesn't work now because you create your npm packages mysterious way. To fix that, you should write your build instructions in package.json and use it for publishing.

Insufficient information on mock failure when argument is object

Consider the following test, which is the simplest example to show a problem with the error information:

   it(`With an object as a parameter, but the wrong one, we get insufficient information back from TypeMoq`, () => {
        let mock = TypeMoq.Mock.ofType(B, TypeMoq.MockBehavior.Strict);
        mock.setup(g => g.g({a:22})).returns(() => -222);
        expect(mock.object.g({a:11})).eql(222);
    });

The message is:
MockException - no setup expression found for ('B.g([object Object])'

This works fine with simple values, of course.

There is an easy fix in this particular case. But when there are complex objects involved as arguments, it would be great to have displayed the full details of the objects concerned, both expected and actual. In my real case, I'm dealing with multiple arguments, all of which are complex objects and/or arrays.

Invoking an odd-number of mocked calls reverses the precedence of the next mock call setup

This probably sounds a little confusing but it's easy to explain with an example. Basically, if I have multiple setups on the same function I expect the newest setup to "win", however if an odd-number of calls to the same mock is made then the oldest setup wins:

Suppose I have the following code executing:

doSomethingBig() {
    ...
    dependency.setSomeValue(value);

    const result = dependency.doSomething();
    ...
}

And I have the following setups:

beforeEach(() => {
    ...
    mockDependency.setup(d => d.setSomeValue(It.isAny())).returns(() => true);
    mockDependency.setup(d => d.doSomething()).returns(() => "hello");
    ...
});

it("doing something big when doing something throws error throws error", () => {
    mockDependency.setup(d => d.doSomething()).callback(() => throw new Error(););

   ...
});

Then I would expect my test to succeed because I have setup doSomething to throw after setting it up to return - newest setup wins.

However, because I have called another mock method with a setup doSomeValue the order is flipped and so when doSomething is called the first setup is executed i.e. returns "hello".

I tracked this down to a suspect use of Array.reverse in ExtractProxyCall.

Array.reverse reverses in-place, which means the ordered calls on the context is mutated and flipped every time ExtractProxyCall is executed (which is once for every setup mock call). Hence, every odd-number of executed calls flips the order of the setups in the context.

Verification of Enum fails

Consider this arrangement:

    enum AnEnum{
        One = 1,
        Two,
        Three
    }

    class AClass {
        property1: string;
        property2: number;
        property3: AnEnum

        amethod(){}
    }

    class CUT{

        do(instance:AClass){

        }
    }

Now we write two tests:

    it('matches without enum', () => {
        const mock = TypeMoq.Mock.ofType(CUT, TypeMoq.MockBehavior.Strict);

        mock.setup(f => f.do(TypeMoq.It.isObjectWith({property1: 'one', property2: 1} as AClass)))
            .verifiable();
        mock.setup(f => f.do(TypeMoq.It.isObjectWith({property1: 'two', property2: 2} as AClass)))
            .verifiable();

        const call1 = new AClass();
        call1.property1 = 'one';
        call1.property2 = 1;
        call1.property3 = AnEnum.One;

        const call2 = new AClass();
        call2.property1 = 'two';
        call2.property2 = 2;
        call1.property3 = AnEnum.Two;

        mock.object.do(call1);
        mock.object.do(call2);

        mock.verifyAll();
    });

    it('does not match with enum', () => {
        const mock = TypeMoq.Mock.ofType(CUT, TypeMoq.MockBehavior.Strict);

        mock.setup(f => f.do(TypeMoq.It.isObjectWith({property1: 'one', property2: 1, property3: AnEnum.One} as AClass)))
            .verifiable();
        mock.setup(f => f.do(TypeMoq.It.isObjectWith({property1: 'two', property2: 2, property3: AnEnum.Two} as AClass)))
            .verifiable();

        const call1 = new AClass();
        call1.property1 = 'one';
        call1.property2 = 1;
        call1.property3 = AnEnum.One;

        const call2 = new AClass();
        call2.property1 = 'two';
        call2.property2 = 2;
        call1.property3 = AnEnum.Two;

        mock.object.do(call1);
        mock.object.do(call2);

        mock.verifyAll(); //THIS FAILS!!
    });

The later test fails. The only difference is the verification of the call that includes an enum value.

Any workaround?

Move @types/lodash to devDependency

I think the @types/lodash dependency in package.json can be moved to devDependencies instead since it doesn't look like the typemoq.d.ts file references it. Right now there's a bug in the lodash definition that causes a compilation error in the newer versions of typescript.

Verifiable by default when Strict mocking

If using the MockBehavior.Strict mocking pattern (i.e. define all setups and then call verifyAll() at the end) the intention is that no code of the mocked type should be called unless there is explicit and matching a setup defined for it. Strict to most developers implies 'verbose', since it more tightly couples the tests the code.

At present, TypeMoq in Strict mode still forces the developer to call mock.verifiable() as well.

So given this class:

class Cut {

    do(dependency:Dependency):number {
        return dependency.something();
    }

    fetch(value:AClass) {
        return value.property;
    }
}

class Dependency {
    something():number {
        return 1;
    }
}

You still have to call .verifiable() for TypeMoq to ensure the setup expectation is called:

describe('simple relationship', function () {
            let dependency:TypeMoq.IMock<Dependency> = TypeMoq.Mock.ofType(Dependency, TypeMoq.MockBehavior.Strict);
            let cut:Cut = new Cut();

            it('cut delegates to dependency', () => {
                dependency.setup(dep => dep.something())
                    .returns(() => 1)
                    .verifiable(TypeMoq.Times.once());  //can get a false positive if this line is not included

                const result = cut.do(dependency.object);

                expect(result).to.equal(1);
                dependency.verifyAll();
            });
});

If you forget to call .verifiable() on the setup, AND the cut does not call the dependency.something() method that was expected, you get a false positive!

Usability issues:

  1. It is easy to forget to call .verifiable() especially when you have lots of setups. As required when using Strict mode, especially with code that has several dependencies.
  2. .verifiable() is by default: .verifiable(TypeMoq.Times.atLeastOnce()). But in Strict mode, we are already opting-in to be strict (and verbose), and 99% of the time the most useful and most precise default is .verifiable(TypeMoq.Times.once()). Which is also ton of extra typing for the majority use-case, especially with a bunch of setups.
  3. Strict mode, should be Strict and unforgiving and precise. But currently, if you forget the call to .verifiable() at all, Strict is rendered very Weak indeed, and that can lead to false positives that are hard to identify and debug.

Suggestion

What if, when using Strict mode on a mock instance, that every call to .setup() automatically called .verifiable(Times.once()) for you, behind the scenes, as the default?

This frees the developer from having to make the explicit call: .verifiable(TypeMoq.Times.once()) at all!

Then the developer can have the option to override the default .verifiable() by explicitly calling .verifiable(TypeMoq.Times.whatever()) to get away from the default behavior.

This would not break existing code.
It does mean update to the docs, since using Strict would now mean .verifiable() is called for you and the default is once() not 'atLeastOnce()' by default.

It would mean that in Strict mode, developers can forget to call .verifiable() and not be penalized with false positives in TDD, AND developers don't have to type: .verifiable(TypeMoq.Times.once()) so many times in a test file, just adding noise.

If developers are not using Strict then there is no change for them, Loose means loose, and the defaults are appropriate in the 'loose' testing pattern (i.e. create only required setups with It.isAny() values, then write specific .verify(whatever, TypeMoq.Times.whatever()) statements for only the stuff you care about).

Create Mock calls constructor

Im trying to setup mock object like thus
let account: TypeMoq.Mock<IAccount> = TypeMoq.Mock.ofType<IAccount>(Account);

Account class has a constructor, and this constructor is called during Mock object creation.
Im not sure if this is made intentionally or not, but obviously when we write test we want to avoid any logic in mocked classes

TypeMoq.Mock.ofType mock property into function.

I use TypeMoq.Mock.ofType<ng.IFormController> to create a mock off ng.IFormController

It seems that the property $valid in ng.IFormController get being mock as function and i can't use it as a property anymore. i even try to assign it as a property and it make the code i am testing not work correctly

for example

if(form.$valid){} would always return true since $valid is function.

It.IsAnyObject only accepts objects/interfaces that has a constructor and prototype not object literals

Because It.IsAnyObject expects Ctor, only types and interfaces that including a constructor and prototype are valid.

But many objects are being instantiated using object literals (JSON deserialization) which does not fit this scheme.

I would suggest to add an overload for It.IsAnyObject that simply expects T

interface z {
new ();
prototype: any;
}
var c = function() {}
var o : z = new c();
var p : z = {}; //<-- not valid

Kind regards

Unable to mock an interface strictly

I'm enjoying using TypeMoq, and especially it's strong Typescript support. Thanks!

With the latest version of TypeMoq:

interface J {
    k(a:number):number;
}
    it(`Mocking an interface without strict works fine`, () => {
        let mock: TypeMoq.IMock<J> = TypeMoq.Mock.ofType<J>();
        mock.setup(jj => jj.k(1)).returns(() => 222);
        expect(mock.object.k(1)).eql(222);
        expect(mock.object.k(2)).eql(undefined);
        mock.verify(jj => jj.k(1), TypeMoq.Times.exactly(1));
    });

    it(`But mocking an interface with strict leads to "no setup expression found"`, () => {
        let mock: TypeMoq.IMock<J> = TypeMoq.Mock.ofType<J>(undefined, TypeMoq.MockBehavior.Strict);
        mock.setup(jj => jj.k(1)).returns(() => 222);
        expect(mock.object.k(1)).eql(222);
        mock.verify(jj => jj.k(1), TypeMoq.Times.exactly(1));
    });

How to mock interface when there is no concrete type?

Hi, thanks for typemoq! Just getting started with it and I'm not sure what to do. Say I want to mock http.IncomingMessage, how would I do that? I have to provide a constructor argument, but it's unclear to me how to do so without implementing the interface myself, and using that class as the constructor argument.

import * as Moq from "typemoq";
import {IncomingMessage} from "http";    

var mockRequest = Moq.Mock.ofType<IncomingMessage>(???);

Mocks with the same verifiable invocation setup multiple times

const m = Mock.ofInstance(a => { });
m.setup(x => x(It.isValue(0))).returns(() => 0).verifiable();
m.setup(x => x(It.isValue(0))).returns(() => 0).verifiable();
m.object(0);
m.object(0);

m.verifyAll();

This fails with Verify Exception: Expected invocation on the mock 2 times, invoked 1 times. Is this not a supported scenario? I have a test where I set up several invocations, and a couple of them end up with the same expected signature. Is it expected that I only register each one once, then verify that it was called the correct number of times?

Mocking methods that already exist on proxied object is impossible

Hi.

I submitted just merged pr: #38, but problem with callable proxy was only a half of solution to my problem.

I wrote an utility that accepts function in constructor. Second argument is an optional context, that - if provided - should be bound to function:

constructor(fn: Function, context?: any) {
   if(context) {
      this.fn = fn.bind(context);
   } else {
      this.fn = fn;
   }
}

I wanted to write test for it:

fnMock.setup(fn => fn.bind(context)).returns(fn => fn);

But such code results in mysterious result:

MockException - more than one setup expression found for ('Function.length'; setup should contain only one expression

First of all, this error message is not very informative. What is an 'setup expression'? It turns out that someone simply tried to call fn.length on my proxied function. But who? Well... fn.bind did!

It turns out that in typmoq es6 proxy implemenation, if property (for example bind) really exists on object, it will be used, instead of mocked/proxied one.

This means that essentially all tests checking calls to functions from prototype chain are impossible to mock (at least in es6 proxy mode).

I did not provide a pr because this behaviour in code seems very deliberate, as seen here (https://github.com/florinn/typemoq/blob/master/src/Proxy/ProxyES6Handler.ts#L30). What is the reason for such behaviour and can we find a way to make existing properties 'mockable' as well?

Thanks in advance and have a great day!

Mock method "returns" implementation is called twice

I'm mocking a method that returns a Promise:

myMock.setup(x => x.method()).returns(() => Promise.reject(new Error("blah")));

I noticed that the "returns" implementation is executed twice even if "method" is called only once on the mock.
This should not be a problem normally, the issue is that in this particular case, the test runner is failing because it detects an unhandled promise rejection.

Is this a known behavior?

ELIFECYCLE with 1.0.0

I have a running karma test with webpack, jasmine and angular2. When I upgrade from 0.3.2 to 1.0.1 my test fails with

 code ELIFECYLCE
 Exit status 32212236505

The npm-debug.log is also not helpful.

14 verbose stack Error: [email protected] test: `karma start --log-level debug`
14 verbose stack Exit status 3221226505
14 verbose stack     at EventEmitter.<anonymous> (C:\Users\mail2\AppData\Roaming\npm\node_modules\npm\lib\utils\lifecycle.js:255:16)
14 verbose stack     at emitTwo (events.js:106:13)
14 verbose stack     at EventEmitter.emit (events.js:191:7)
14 verbose stack     at ChildProcess.<anonymous> (C:\Users\mail2\AppData\Roaming\npm\node_modules\npm\lib\utils\spawn.js:40:14)
14 verbose stack     at emitTwo (events.js:106:13)
14 verbose stack     at ChildProcess.emit (events.js:191:7)
14 verbose stack     at maybeClose (internal/child_process.js:885:16)
14 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)

Cannot stub a part of methods

it('abc', () => {
    const m = Mock.ofInstance({
        a() { return 1; },
        b() { return this.a(); },
    });
    m.callBase = true;

    expect(m.object.a()).equal(1);
    expect(m.object.b()).equal(1);

    m.setup(x => x.a()).returns(() => 2);
    expect(m.object.a()).equal(2);
    expect(m.object.b()).equal(2); // FAIL
});

Setup vs Verify

To be honest, I dont understand why there are two methods. I have used some rhino mocks and FakeItEasy and especially the last framework is much easier to use.

I would expect something like:

undoRedoService.when(e => e.redo()).once().returns(true);
undoRedoService.when(e => e.redo()).times(17).throws(...);

mocks.verifyAll();

I don't like that you have to duplicate the stuff:

undoRedoService.setup(e => e.redo())returns(true);

sut.redo();

undoRedoService.verify(e => e.redo(), Times.once());

Mock a static class

Is it possible to mock a static class?

E.g. This is a fairly common pattern in our code base...

class Greeter {
    private static _instance: Greeter | null;
    static instance(): Greeter {
        if (!this._instance) {
            this._instance = new Greeter();
        }
        return this._instance;
    } 
    
    greet(): string {
        return 'Hello';
    }
}

Consumers require the Greeter module and use Greeter.instance() to get the singleton instance of Greeter.

I would like to mock the instance method so it returns my own mocked version of Greeter.

We use a combination of TypeMoq and Mockery in our tests, but this is the first time I've tried to mock a static member.

I don't see any example like this in the README. If this is possible, could an example be added?

Dynamic mocking with Proxies

I came here with the same question as in #16, and it sounds like you need an instance of the mocked object so you can grab its properties and add them to your mock proxy. I was wondering if you ever thought about solving this with the new ES6 Proxy, which would let you intercept calls in 'setup'. It's basically designed for this scenario. We would be able to write

.setup(m => m.myFunction())

and it would call the 'get' handler on your Proxy object with 'myFunction' as an argument, for example. Does that make sense?

I would find this especially useful because I'm trying to mock an API which is defined with a .d.ts file + a Proxy object, so there is nothing to query the properties from.

Build as UMD

You don't have to separate namespaces (typemoq.d.ts) and modules (typemoq.node.d.ts). Distribute it as UMD

Add emit function to setup

I think that it would be cool if there was a way to have an event emitted when a function is called. This is useful for mocking streams or other objects that emit events and you are trying to make sure that when those events are emitted, the appropriate code works.

Example

mock.setup(obj => load()).emit("loaded");

Function Definition

interface IMock {
    emit(eventName: string, ...args: any[]): void
}

Multiple setups on same method call mutate previously recorded values

Oh boy! this one has been hard to track down, but I think I have found the bug in TypeMoq related to multiple multiple setups on the same method, but with different data. (that I thought I had found in #59 ).
(I can confirm that C# Moq does the right thing by treating recorded results as immutable)

Given the following definitions:

class AClass {
        property1: string;

        amethod() {
        }
    }

    class CUT {

        do(instance: AClass) {

        }
    }

This test fails in TypeMoq today:

    it('should not fail when changing recorded variables', () => {
        const mock = TypeMoq.Mock.ofType(CUT, TypeMoq.MockBehavior.Strict);

        mock.setup(f => f.do(TypeMoq.It.isObjectWith({
            property1: 'one',
        } as AClass)))
            .verifiable();
        mock.setup(f => f.do(TypeMoq.It.isObjectWith({
            property1: 'two',
        } as AClass)))
            .verifiable();

        let value = {property1: 'one'} as AClass;
        mock.object.do(value);

        value.property1 = 'two';
        mock.object.do(value);

        mock.verifyAll(); // SHOULD NOT FAIL!
    });

This is the stack-trace:

MockException - invocation count verification failed (expected invocation of CUT.do(It.isObjectWith({"property1":"one"})) at least once, invoked 0 times
 Configured setups:
 CUT.do(It.isObjectWith({"property1":"one"})), at least once
 CUT.do(It.isObjectWith({"property1":"two"})), at least once

 Performed invocations:
 CUT.do({"property1":"two"})
 CUT.do({"property1":"two"})

)
    at MockException.Error (native)
    at MockException.Exception [as constructor] (node_modules\typemoq\dist\Error\Error\Error\Exception.ts:3:9)
    at new MockException (node_modules\typemoq\dist\Error\Error\Error\MockException.ts:20:9)
    at InterceptorExecute.throwVerifyCallCountException (node_modules\typemoq\dist\InterceptorExecute.ts:65:17)
    at InterceptorExecute.verifyCallCount (node_modules\typemoq\dist\InterceptorExecute.ts:54:18)
    at InterceptorExecute.verify (node_modules\typemoq\dist\InterceptorExecute.ts:41:18)
    at StaticMock.MockBase.verifyAll (node_modules\typemoq\dist\MockBase.ts:61:31)
    at Context.it (src\sqsLoader\TypeMoqBug.ts:159:14)

The interesting part is the 'Performed invocations' list, that show us that at the time of the verifyAll() for each call to mock the data has already been changed from what it would have been on the first call.

Problem: The issue it seems (I have not looked at the TypeMoq code, but assume) that when recording a value of a call to a mock, the recorded values are being saved (as references) - 'mutable' references.

If the CUT makes a call on the mock and then changes a value of a recorded reference that was made in that first call, the mocks recorded reference is also updated, and that causes the verifyAll() to see that the calls were made with the updated reference, not the data as it was at the time of the call. As we can see from the stack-trace.

Solution: The recorded data by the mock should be immutable (i.e. deep-cloned), so that teh CUT cannot mutate it later.

Doesn't verify invocation order

it.only('test', () => {
    const mock = Mock.ofInstance((x: number) => { });

    // expected invocation order is 1 then 2
    mock.setup(f => f(1)).verifiable(Times.once());
    mock.setup(f => f(2)).verifiable(Times.once());

    // actual invocation order is 2 then 1
    mock.object(2);
    mock.object(1);

    // therefore verification should fail
    expect(() => mock.verifyAll()).throw();
});

Include name of the function call in NoSetup exceptions

hi there, first off thank you very much for building and maintaining this library. It makes testing in TypeScript so much easier and I've found it incredibly useful.

I have just one issue that makes debugging kind of difficult at times - I use MockBehavior.Strict to stop any original methods being called, but when they are called the NoSetup exception doesn't tell me what call it is. Knowing which function was called would make patching the test much easier, as it stands I have to read through my existing classes (my most-mocked test has about 7 mocked classes) and try to find out which one has a missing setup.

If you could point me in the right direction I can code something like this myself. I could add a message to the areas that call MockException with the reason as NoSetup, but I'm not sure where to pull the class or method name from.

Thanks in advance.

TypeMoq.It.isAny() does not match on 'undefined'

When I call the mocked object method with undefined:
mock.object.someMethod(undefined);

Then verify, using isAny, it passes, but it shouldn't:
mock.verify(x => x.someMethod(TypeMoq.It.isAny()), TypeMoq.Times.never());

Then verify, specifying undefined, instead of isAny, it fails, as it should:
mock.verify(x => x.someMethod(undefined), TypeMoq.Times.never());

It not possible to return falsy values for properties

Hi,

I want to test a scenario where I need

if (obj.prop)

evaluates to false. Unfortunately, obj.prop is always truthy, because event if I set it up with a lambda returning false or undefined it will return a function (related to ES6 Proxy I suppose).
This occurs even if I want to return 0.

It would be great if there was a way (besides using strict behavior) to explicitly return falsy values.

Losing verifiable context with inner functions

First, awesome library! Thank you.

I have a class that I need to return a function. It will call methods inside the same class. It looks something like the following...

class Foo {
  register(): () => void {
    return () => {
      this.canExecute();
    };
  }

  canExecute(): void {
    console.log('>> in canExecute <<');
  }
}

I want to verify that canExecute is being called, and it is. The problem lies in the fact that TypeMoq doesn't see it being called. I have the following test...

describe('Foo', () => {
  it('when register() invoked calls canExecute()', () => {
    let mock: IMock<Foo> = Mock.ofType(Foo);
    mock.callBase = true;
    const registerInnerFunction = mock.object.register();

    registerInnerFunction();

    mock.verify(x => x.canExecute(), Times.once());
  });
});

And get the following output...

  Foo
>> in canExecute <<
    1) when register() invoked calls canExecute()


  0 passing (30ms)
  1 failing

  1) Foo when register() invoked calls canExecute():
     MockException - invocation count verification failed (expected invocation of Foo.canExecute() 1 times, invoked 0 times
      at MockException.Exception [as constructor] (node_modules/typemoq/dist/Error/Error/Error/Exception.ts:3:9)
      at new MockException (node_modules/typemoq/dist/Error/Error/Error/MockException.ts:20:9)
      at InterceptorExecute.throwVerifyCallCountException (node_modules/typemoq/dist/InterceptorExecute.ts:55:17)
      at InterceptorExecute.verifyCallCount (node_modules/typemoq/dist/InterceptorExecute.ts:51:18)
      at StaticMock.verify (node_modules/typemoq/dist/StaticMock.ts:66:31)
      at Context.it (src/foo.spec.ts:87:10)

Thanks again for the great work!

Not matching public properties?

I'm attempting to create a mock for AWS.S3, but I'm getting a error:

error TS2322: Type 'Mock<S3>' is not assignable to type 'S3'.
  Property 'endpoint' is missing in type 'Mock<S3>'.

My code looks like:

import {S3} from "aws-sdk";
import * as TypeMoq from 'typemoq';

function createS3ClientMock():S3 {
  const mock:TypeMoq.Mock<S3> = TypeMoq.Mock.ofType(S3);

  return mock;
}

The definition for S3 looks like:

export declare class S3 {
    constructor(options?: any);
    endpoint: Endpoint;

    getObject(params: s3.GetObjectRequest, callback?: (err: Error, data: any) => void): any;
    putObject(params: s3.PutObjectRequest, callback: (err: Error, data: any) => void): void;
    deleteObject(params: s3.DeleteObjectRequest, callback: (err: Error, data: any) => void): void;
    headObject(params: s3.HeadObjectRequest, callback: (err: Error, data: any) => void): void;
    getSignedUrl(operation: string, params: any): string;
    getSignedUrl(operation: string, params: any, callback: (err: Error, url: string) => void): void;
    upload(params?: s3.PutObjectRequest, options?: s3.UploadOptions, callback?: (err: Error, data: any) => void): void;
    listObjects(params: s3.ListObjectRequest, callback: (err: Error, data: s3.ListObjectResponse) => void): void;
    listObjectsV2(params: s3.ListObjectV2Request, callback: (err: Error, data: s3.ListObjectV2Response) => void): void;
    waitFor(state: string, params: s3.HeadObjectRequest, callback: (err: Error, data: any) => void): void;

    createMultipartUpload(params: any, callback: (err: Error, data: any) => void): void;
    uploadPart(params: any, callback: (err: Error, data: any) => void): void;
    listParts(params: any, callback: (err: Error, data: any) => void): void;
    completeMultipartUpload(params: any, callback: (err: Error, data: any) => void): void;
  }

I'm able to hack my way around this, by doing something like:

function createS3ClientMock():S3 {
  const mock: any = TypeMoq.Mock.ofType(S3);
  mock.endpoint = 'STUBBED_ENDPOINT';
  return <S3> mock;
}

Module export issue

I'm trying to update to the latest version of typemoq but it seems like that the definition files are not compatible with typescript 1.8.9.

Here's a poc project to reproduce the issue:

index.ts

import typemoq = require("typemoq");

console.log("Alma")

tsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
        "isolatedModules": false,
        "jsx": "react",
        "experimentalDecorators": false,
        "emitDecoratorMetadata": false,
        "declaration": false,
        "noImplicitAny": false,
        "removeComments": true,
        "noLib": false,
        "preserveConstEnums": true,
        "suppressImplicitAnyIndexErrors": true,
        "outDir": "output",
        "sourceMap": true
    },
    "compileOnSave": true,
    "buildOnSave": false,
    "exclude": [
        "node_modules"
    ],
    "atom": {
        "rewriteTsconfig": false
    }
}

package.json

{
  "name": "typemoqtest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "typemoq": "0.1.0"
  },
  "author": "",
  "license": "ISC"
}

And the error that I get is: index.ts(1,26): error TS2656: Exported external package typings file 'C:/Users/ter/Work/typemoqtest/node_modules/typemoq/typemoq.node.d.ts' is not a module. Please contact the package author to update the package definition.

Creating a Mock calls original constructor

When I create a mock:

mockChatService = TypeMoq.Mock.ofType(ChatService);

Original constructor of ChatService is called, so any code in constructor for example:

constructor (private dataService:DataService) { this.dataService.addListener('sampleEvent', sampleHandler); }

causes null pointer exception on this.dataService.

Cannot chain callback and verifiable without an intermediary

it('test', () => {
    const mock = new Mock<() => void>(() => {});

    mock.setup(x => x()).callback(() => {}).callBase().verifiable(Times.never());
    // compiler says OK

    mock.setup(x => x()).callback(() => {}).returns(() => null).verifiable(Times.never());
    // compiler says OK

    mock.setup(x => x()).callback(() => {}).verifiable(Times.never());
    // compiler says error TS2339: Property 'verifiable' does not exist on type 'IReturnsThrows<() => void, void>'.
    // But there is no any runtime error, it works! :-)

    mock.verifyAll();
});

Feature Request: More Matches

Hi, I have several feature requests:

  1. TypeMoq.It.isEquals(x: any) <-- Make deep object comparison
  2. TypeMoq.It.is(v => v.xyz.isEqualsTo(abc)) <-- Custom predicate

Doesn't support TypeScript 1.6 npm package typing resolving

TypeScript 1.6 has introduced a new way to load typings that are bundled with npm packages:
https://github.com/Microsoft/TypeScript/wiki/Typings-for-npm-packages

I tried to add a line into typemoq packages.json to declare the typing file:

  "typings": "dist/typemoq.node.d.ts",

But I got error when compile my project which imports typemoq:

error TS2656: Exported external package typings file 'C:/test/node_modules/typemoq/dist/typemoq.node.d.ts' is not a module. Please contact the package author to update the package definition.

Mock setup fails when using polyfilled Proxy

I've got a test suite that I'm now trying to get to run under Node 4.x. As explained in the readme, the dynamic mocks require ES6's Proxy object, which is not available by default in Node 4.x, and I get a MockException as expected:

MockException - invalid dynamic proxy runtime (ES6 Proxy object not detected; the dynamic mocking feature requires ES6 Proxy object support

So, to make the tests run, I've attempted to polyfill the Proxy object using proxy-polyfill. However, now the tests fail when setting up the mocks. Here's an example of a test:

const sink = TypeMoq.Mock.ofType<Sink>();
sink.setup(m => m.flush()).returns(() => Promise.resolve());
const sinkStage = new SinkStage(sink.object);
return sinkStage.flush().then(() => {
  sink.verify(m => m.flush(), TypeMoq.Times.once());
});

This gives me the following error instead (47:25 points to m.flush() inside the call to setup:

TypeError: m.flush is not a function
at test\sink.spec.ts:47:25
at MethodCallReturn.MethodCall (node_modules\typemoq\dist\MethodCall.ts:28:9)
at new MethodCallReturn (node_modules\typemoq\dist\MethodCallReturn.ts:19:9)
at Function.MethodCallReturn.ofDynamicMock (node_modules\typemoq\dist\MethodCallReturn.ts:34:22)
at DynamicMock.setup (node_modules\typemoq\dist\DynamicMock.ts:32:37)
at Context. (test\sink.spec.ts:47:12)

Is this a problem/limitation with the Proxy polyfill, or is it TypeMoq that does something weird with it?

Improve Documentation

I think that this is a really cool system for mocking objects in typescript but I feel like the documentation is a little bit lacking in explaining how it is used. I have spent a couple of hours trying to figure out how to use your package. It is really hard to understand what your verify and setup functions work and what the parameters to them are. A good way to do that would be to add comments like at the end of #30.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.