florinn / typemoq Goto Github PK
View Code? Open in Web Editor NEWA simple mocking library for TypeScript
License: MIT License
A simple mocking library for TypeScript
License: MIT License
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?
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?
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.
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".
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));
}
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
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?
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";
});
it('test', () => {
const mock = Mock.ofInstance<() => void>(() => {});
const obj = mock.object;
mock.reset();
obj();
mock.verify(f => f(), Times.once());
});
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.
Being able to override setups would greatly improve the convenience of writing tests for me.
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)));
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:
B.doSomething
.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.
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.
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.
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.
This looks like an interesting project, I'd like to use it in jasmine/karma tests. Are there any plans to register this?
$ bower search typemoq
No results.
$ tsd query typemoq
zero results
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?
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.
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!
.verifiable()
especially when you have lots of setups. As required when using Strict
mode, especially with code that has several dependencies..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.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.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 setup
s with It.isAny()
values, then write specific .verify(whatever, TypeMoq.Times.whatever())
statements for only the stuff you care about).
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
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.
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
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));
});
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>(???);
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?
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!
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?
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)
typemoq.d.ts
and typemoq.node.d.ts
contain incorrect source map path
//# sourceMappingURL=output.d.ts.map
.
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
});
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());
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?
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.
You don't have to separate namespaces (typemoq.d.ts) and modules (typemoq.node.d.ts). Distribute it as UMD
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.
mock.setup(obj => load()).emit("loaded");
interface IMock {
emit(eventName: string, ...args: any[]): void
}
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.
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();
});
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.
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());
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.
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!
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;
}
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.
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.
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();
});
Hi, I have several feature requests:
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.
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?
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.