Giter Site home page Giter Site logo

ts-mockito's People

Contributors

andrew avatar artifexet avatar bendykowski avatar bricka avatar bryancrotaz avatar cakeinpanic avatar dreef3 avatar freekh avatar gianlucamateo avatar golergka avatar insightfuls avatar jjordan-dff avatar jlkeesey avatar johanblumenberg avatar kwolfy avatar markus-ende avatar mcampagonzalez avatar michalstocki avatar mikeporterdev avatar nagrock avatar nknapp avatar ryutaro-brainlabs avatar sennett avatar srosato avatar thomashilzendegen avatar vnalupta 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

ts-mockito's Issues

Verify does not work when the method under verification has more than 1 argument

Verify does not work when the method under verification has more than 1 argument. This is because in the method isApplicable of the class MethodAction the variable index is not being incremented.

Bellow is the method isApplicable already fixed.

 public isApplicable(methodName:string, matchers): boolean {
        if (this.methodName != methodName) {
            return false;
        }
        let allValid = true;
        let index: number = 0;
        for (let arg of this.args) {
            if (matchers[index] && !matchers[index].match(arg)) {
                allValid = false;
            }
            index++;
        }
        return allValid;
    }

wrong spying behavior

Thank for great library!

I found unexpected behavior with properties

ts-mockito version: 2.2.5

import {spy} from "ts-mockito";

class Foo {
  counter: number;
  constructor() {
    this.counter = 111;
  }
  hello(name: string) {
    return `Hello ${name} ${this.counter}!`;
  }
}

const foo: Foo = new Foo();
const mockedFoo = spy(foo);

console.log(foo.hello("world"));
/*
result: Hello world function () {
            var args = [];
            for (var _i = 0; _i < arguments.length; _i++) {
                args[_i] = arguments[_i];
            }
            var action = new MethodAction_1.MethodAction(key, args);
            _this.methodActions.push(action);
            var methodStub = _this.getMethodStub(key, args);
            methodStub.execute(args);
            return methodStub.getValue();
        }!
*/

How to mock async functions?

I have issues with mocking an async function. I assume that I can return a promise when the mocked method is called, so that the then function can be called on that promise. However when running the test, I get the following error:

  1) LoginSpec
       login should return a valid app token:
     TypeError: Cannot read property 'then' of null
      at Promise (src/login.js:1:11787)
      at new Promise (<anonymous>)
      at LoginService.getToken (src/login.js:1:11319)
      at LoginService.<anonymous> (src/login.js:1:9410)
      ...

Test class:

import {expect} from 'chai';
import {suite, test} from "mocha-typescript";
import {anything, instance, mock, when} from "ts-mockito";
import {LoginService} from '../src/login';
import {RestAccess} from "../src/rest";

@suite
class LoginSpec {

    private restMock = mock(RestAccess);

    @test.only
    public async 'login should return a valid app token'() {
        // given
        const ssoToken = {
            access_token: 'AccessToken',
            refresh_token: 'RefreshToken',
        };

        const promise = new Promise((resolve, reject) => {
            resolve(ssoToken);
        });

        when(this.restMock.fetchJson('url', anything))
            .thenReturn(promise);

        const sut = new LoginService(instance(this.restMock));

        // when
        const event = {
            queryStringParameters: {
                code: 'ssoCode',
            },
        };

        const appToken = await sut.login(event);

        // then
        const decodedToken = this.auth.decodeToken(appToken);
        ...
    }
}

Call to mock:

private getToken(code: string): Promise<any> {
        return new Promise((resolve, reject) => {
            const options = {
                ...
            };

            this.rest.fetchJson('url', options).then(result => {
                console.log('resolve');
                resolve(result);
            }).catch(err => {
                reject(err);
            });
        });
    }

Mocked method:

    public async fetchJson(url: string, options: any) {
        const response = await fetch(url, options);
        const data = await response.json();
        return data;
    }

package.json

{
  "dependencies": {
    "@types/jsonwebtoken": "^7.2.5",
    "@types/mysql": "^2.15.3",
    "@types/node-fetch": "^1.6.7",
    "jsonwebtoken": "^8.2.0",
    "mysql": "^2.15.0",
    "node-fetch": "^2.1.1"
  },
  "devDependencies": {
    "@types/aws-lambda": "0.0.33",
    "@types/chai": "^4.1.2",
    "@types/mocha": "^2.2.48",
    "chai": "^4.1.2",
    "eslint": "^4.18.2",
    "eslint-plugin-mocha": "^4.12.1",
    "mocha": "^5.0.4",
    "mocha-typescript": "^1.1.12",
    "nyc": "^11.4.1",
    "serverless-offline": "^3.18.0",
    "serverless-plugin-typescript": "^1.1.5",
    "ts-mockito": "^2.3.0"
  },
  "scripts": {
    "pretest": "tsc",
    "test": "nyc mocha",
    "watch": "mocha-typescript-watch",
    "prepare": "tsc"
  }
}

Import functions other than mock, when, verify and instance

How should i import functions other than mock, when, verify and instance ?
Since in the main file (lib/ts-mockito.js) only those 4 functions are exported how should import other functions like anything ? This without specifying the path to the specific file where the function is exported.

Mocking class with constructor arguments

Say we have a class like so:

export default class FileLoader {
  private fileToLoad: string
  public constructor(fileToLoad: string) {
    this.fileToLoad = fileToLoad;
    this.loadFile(); 
  }

  private loadFile() {
    ...
  }
}

I don't see any way to create a mock of the FileLoader and and instantiate it and pass parameters to the constructor.

named verifys

Hey, it would be very useful to be able to name the verify statements so that when fail, its easier to identify them.

awesome library btw!!

Unexpected behaviour of multiple stubbings for a single method

There is a general problem with the way ts-mockito handles stubbing multiple behaviours for the single method.
As official documentation of Java Mockito states clear:

Once stubbed, the method will always return stubbed value regardless of how many times it is called.

Last stubbing is more important - when you stubbed the same method with the same arguments many times.

ts-mockito works differently. When stubbing a method with different arguments โ€“ it affects the other stubbings of the same method.

Stubbing calls with different arguments

Current behaviour

when(mock.someMethod("some arg").thenReturn(10);
when(mock.someMethod("some other arg").thenReturn(20);

const object = instance(mock);
object.someMethod("some arg"); // returns 10
object.someMethod("some arg"); // returns null
object.someMethod("some arg"); // returns null

object.someMethod("some other arg"); // returns 20
object.someMethod("some other arg"); // returns null
object.someMethod("some other arg"); // returns null

Expected behaviour

when(mock.someMethod("some arg").thenReturn(10);
when(mock.someMethod("some other arg").thenReturn(20);

const object = instance(mock);
object.someMethod("some arg"); // returns 10
object.someMethod("some arg"); // returns 10
object.someMethod("some arg"); // returns 10

object.someMethod("some other arg"); // returns 20
object.someMethod("some other arg"); // returns 20
object.someMethod("some other arg"); // returns 20

Stubbing overriding

Current behaviour

when(mock.someMethod("some arg").thenReturn(10);
when(mock.someMethod("some arg").thenReturn(20);

const object = instance(mock);
object.someMethod("some arg"); // returns 10
object.someMethod("some arg"); // returns 20
object.someMethod("some arg"); // returns null

Expected behaviour

when(mock.someMethod("some arg").thenReturn(10);
when(mock.someMethod("some arg").thenReturn(20);

const object = instance(mock);
object.someMethod("some arg"); // returns 20
object.someMethod("some arg"); // returns 20
object.someMethod("some arg"); // returns 20

Stubbing multiple behaviours for the same arguments

Current behaviour

when(mock.someMethod("some arg").thenReturn(10, 20); // Compilation Error
when(mock.someMethod("some other arg")
  .thenReturn(10)
  .thenReturn(20); // Compilation Error

Expected behaviour

when(mock.someMethod("some arg").thenReturn(10, 20);
when(mock.someMethod("some other arg")
  .thenReturn(10)
  .thenReturn(20);

const object = instance(mock);
object.someMethod("some arg"); // returns 10
object.someMethod("some arg"); // returns 20
object.someMethod("some arg"); // returns 20

object.someMethod("some other arg"); // returns 10
object.someMethod("some other arg"); // returns 20
object.someMethod("some other arg"); // returns 20

Need to specify particular params for mock call

###When I have updated from 2.3 to 2.9 I found out that these constructions don't work anymore:

const testServiceMock = mock<TestService>(TestService);
when(testServiceMock.hello(anything())).thenReturn('a')

const testService = new TestService();
testService.hello(); // mock won't work cause I specified that it should work only when 1 argument is passed
testService.bye(); // mock won't work cause i haven't specified it at all

Ability to use anything() for not provided parameters was great(and totally in js way), why did you took it away?(

Verify not working well with arrays as parameter

Hey,

I noticed when I do a verify on a function that takes an array, for instance:

verify(router.navigate(['/login'])).called();

It tells me

Error: Expected "navigate(strictEqual(/login))" to be called at least 1 time(s).

If I capture the arguments and then do an expect, it does work. Somehow it removed the array around it...

Logic in public getters is actually executed when instantiating the mock

If you have a class as follows

export class TestClass {
    constructor(private dependency: Dependency) { }
    public get myProperty(): string {
        return this.dependency.getVal();
    }
}

when running
let myMock = mock(TestClass);

this.dependency.getVal() will actually get executed, and fail since this.dependency will be undefined.
Occurs when generating method stubs

Spies not returning values from method calls

I am spying on an instance like this:

const runner: Runner = new Runner()
const spyRunner = spy(runner)
when(spyRunner.myFunc()).thenReturn(10000)
expect(spyRunner.now()).to.equal(10000)

The test fails with:

expected { Object (methodStubCollection, matchers, ...) } to equal 10000

It seems that invoking the method is not returning the desired result, but some transient object. Also, if I call another method that I have not setup with "when", I get the same type of object back.

What am I doing wrong?

Karma throws exception

Karma throws this exception launching tests with ts-mockito:

Error: XHR error (404 Not Found) loading http://localhost:9876/ts-mockito

multiple instances of mocked objects

Hi,
When I was trying out ts-mockito I noticed that the instance() method does not create different instances of the mocked Class.

For example I have a class User with a field id. When creating two mocked objects:

let mockedUser = mock(User);
let user1 = instance(mockedUser);
let user2 = instance(mockedUser);
if(user1.id === user2.id)
  return true;
else return false;

This code yields true. Am I using the instance method in the wrong way?

ImmutableJS integration

Using ImmutableJS results in being unable to mock the interfaces defined. I wonder if there is a way to have these some sort of fix or integration to support it.

Mocker is undefined

I'm trying to unit test a token service, but I get the error:

TypeError: Cannot read property 'getAllMatchingActions' of undefined
    at MethodStubVerificator.times (/Users/ryuuji3/Projects/Node/restaurant-manager/restaurant-manager-server/node_modules/ts-mockito/src/MethodStubVerificator.ts:32:63)
    at MethodStubVerificator.once (/Users/ryuuji3/Projects/Node/restaurant-manager/restaurant-manager-server/node_modules/ts-mockito/src/MethodStubVerificator.ts:20:14)
    at Object.<anonymous> (/Users/ryuuji3/Projects/Node/restaurant-manager/restaurant-manager-server/src/services/token.spec.ts:46:11)
    at Generator.next (<anonymous>)
    at fulfilled (/Users/ryuuji3/Projects/Node/restaurant-manager/restaurant-manager-server/src/services/token.spec.ts:4:58)
    at <anonymous>

Here is my test:

  describe('issue()', () => {
    let mockRepository : TokenRepository, repository : TokenRepository
    let user : User
    let jwt : string
    let token: Token
    let service : TokenService

    before(async () => {
      mockRepository = mock(TokenRepository)
      user = mockUser('example')

      let payload : PayloadI = Token.createPayload(user)
      jwt = await Token.sign(payload)
      token = await Token.create(user, jwt)

      when(mockRepository.register(user, jwt)).thenResolve(token)

      repository = instance(mockRepository)
      service = new TokenService(repository)
    })

    it('should call repository.register()', async () => {
      await service.issue(user)
        verify(
          repository.register(user, jwt)
        ).once()
    })
  })

Any idea of what's going wrong?

EDIT:
It appears I should have read the documentation better.
In order to check for behaviour, rather than return, you must verify the mocker method not the instance method.

Sorry!

Resetting particular stub

This is more of a question than an issue. I just started using ts-mockito and I am wondering if it is possible to "re-stub" a method to return different value? I am stubbing my method in beforeEach with a value that works for all tests but there is one particular test where I want it to return a different value. I know I can reset the mock, but that would remove ALL of the stubs, while I just want to change one. Is it possible?

Maximum call stack size exceeded

With 2.2.8, I got "Maximum call stack size exceeded" error and don't have any idea where to start investigation. 2.2.7 works successful BTW.

HeadlessChrome 0.0.0 (Linux 0.0.0) SubscribeComponent should create FAILED
	Failed: Maximum call stack size exceeded
	RangeError: Maximum call stack size exceeded
	    at Mocker.webpackJsonp.../../../../ts-mockito/lib/Mock.js.Mocker.createInstancePropertyDescriptorListener home/circleci/project/front/node_modules/ts-mockito/lib/Mock.js:96:1)
	    at Object.get home/circleci/project/front/node_modules/ts-mockito/lib/Mock.js:48:1)
	    at isUnconfigurable home/circleci/project/front/node_modules/zone.js/dist/zone.js:2185:1)
	    at Function.Object.defineProperty home/circleci/project/front/node_modules/zone.js/dist/zone.js:2148:1)
	    at Mocker.webpackJsonp.../../../../ts-mockito/lib/Mock.js.Mocker.createInstancePropertyDescriptorListener home/circleci/project/front/node_modules/ts-mockito/lib/Mock.js:99:1)
	    at Object.get home/circleci/project/front/node_modules/ts-mockito/lib/Mock.js:48:1)
	    at isUnconfigurable home/circleci/project/front/node_modules/zone.js/dist/zone.js:2185:1)
	    at Function.Object.defineProperty home/circleci/project/front/node_modules/zone.js/dist/zone.js:2148:1)
	    at Mocker.webpackJsonp.../../../../ts-mockito/lib/Mock.js.Mocker.createInstancePropertyDescriptorListener home/circleci/project/front/node_modules/ts-mockito/lib/Mock.js:99:1)
	    at Object.get home/circleci/project/front/node_modules/ts-mockito/lib/Mock.js:48:1)

Is there any known issues related with this?

Results capture

Whether there are plans to realize capture of results. I could help with the implementation. Something like that:

class Foo {
  bar(a: number) {
    return a + 1;
  }
}

const foo = new Foo();
const mockedFoo = spy(foo);

foo(11);
captureResults(mockedFoo.bar).last(); // 12

//Or with breaking changes

capture(mockedFoo.bar).last().result; // 12
capture(mockedFoo.bar).last().args; // [11]

verify() should consider once() by default

I found out that it's really easy to forget the call count verification:

verify(myMock.getFoo());

That will always pass and the developer will hardly notice that something is missing, since our team has a Java background. In java we could use both ways:

verify(myMock).getFoo();
verify(myMock, times(1)).getFoo();

If you call verify without anything else, it's implicit that you want to check it was called once.

I tried to find (or even thinking to implement) a tslint rule that will ensure that verify is never called without the call count verification method (once(), called(), etc), but I believe it would be better if ts-mockito would assume that a verify is always once() by default unless specified otherwise.

Passing parameters to the constructor of a mocked class

Hi,

I want to mock a class that uses parameters in the constructor.
That class is a JS class (no TypeScript involved) and I need to pass a value to the constructor in order to create an instance of the class.

That is basically my test so far:

// import ts-mockito
import {mock, when, instance} from 'ts-mockito';

// needed for signature
import { TradeOffer } from 'steam-tradeoffer-manager';

// needed to get ts-mockito's clazz working
const TradeOffer = require("../../node_modules/steam-tradeoffer-manager/lib/classes/TradeOffer.js");

// original constructor is TradeOffer(manager, partner, token)
let mockedTradeOffer:TradeOffer = mock(TradeOffer);

// instantiation fails because the constructor checks if "partner" is valid
let offer = instance(mockedTradeOffer);

Do you have any ideas on how I can tackle that problem? Or do we need a new feature here? ^^

Issue spying entire modules and use it with proxyquire

Hi there. First at all many thanks for creating this amazing lib, I were looking for something like this for years.

So I was trying to use ts-mockito with proxyquire, when I realise that it might be an issue on ts-mockito when trying to spy a module (specially singleton modules) like the fs module of node.js
Apparently proxyquire/typescript (don't know who does the magic) is able to deal with the problematic of commonjs modules conversion to es modules, and the lack of .default.
When manual test doubles are created and send to proxyquire reach the other side with no problems. But when ts-mockito is used, errors like this are shown:
fs_extra_1.default.readFile is not a function

I've crated a repo to show how to use ts-mockito and proxyquire toggether and also exposing this issue. Also a better and detailed explanation of the issue, and a possible solution.
https://github.com/danyg/ts-mockito-proxyquire

When running npm test you will see that there is a test failing which is the issue itself, as I believe is how any developer would expect to use spy to mock a module.

Hope this helps.

Why we need "instance()"?

Hi, I'm trying to understand why we need a separate function (instance()) to get an instance of a mocked class, since in the original (Java) version of mockito, mock() returns an instantiated object.

There is some technical limitation in Typesctipt?

Mocking abstract classes

I see that this is not supported yet:

'Argument of type 'typeof AbstractClass' is not assignable to parameter of type 'new (...args: any[]) => AbstractClass'.
Cannot assign an abstract constructor type to a non-abstract constructor type.'

Can this be supported in TypeScript or not yet possible?

Thanks!

mock<T> declared return type of T, but returnns not an instance of T

I started just started using this library. And had some problems getting starting, because I havent seen that instance(...) is needed.

I would expect that mock(...) would return some Generic type Mock<T> that will be used by the instance(...) method.

Then the compiler would throw an error.

Unable to mock classes that make call to 'toString()'

When mocking a class that contains a method, that internally calls toString() I get the following error when the toString() method is invoked on the mocked instance itself.

TypeError: methodStub.hasMatchingInAnyGroup is not a function
	    at Mocker.webpackJsonp.../../../../ts-mockito/lib/Mock.js.Mocker.getMethodStub home/dev/src/ui/~/ts-mockito/lib/Mock.js:183:1)
	    at Proxy.<anonymous> home/dev/src/ui/~/ts-mockito/lib/Mock.js:115:1)

I guess that is related to the same problem like in #28

When I was debugging the ts-mockito code, I could see, that https://github.com/NagRock/ts-mockito/blob/master/src/utils/MockableFunctionsFinder.ts returned a positive match on my dummy() function that contains the toString() invocation and defines the toString() method as a mockable function, even though this is not needed / required.

This is a jasmine test example I used to reproduce the error:

import {instance, mock} from "ts-mockito";

describe("toString", () => {

	it("should not break on toString", () => {
		const dummyMock: Dummy = mock(Dummy);
		const dummyInstance: Dummy = instance(dummyMock);

		dummyInstance.toString();
	});
});

export class Dummy {

	public dummy(): void {
		window.toString();
	}
}

This behavior causes problems in our test setup, where jasmine wants to create a human readable error message, in case an assertion failed. However if the expected object contains a mock of a class like the Dummy class on top with a toString() method in the body of a function, it will fail and therefore hide the actual failed expectation.

Weirdly enough when i comment out the window.toString() line the MockableFunctionsFinder.ts still matches the given toString() function. As stated in the comment of that class, it is greedy but it even captures comments and so on.

Stubbing method same params value twice on same mock take the first one not last one

Indented behavior is last stubbing is more important and should be used.

when(mock(mockObject.method())).thenReturn(false);
when(mock(mockObject.method())).thenReturn(true);

Return false.
it should return last stubbing value, true.

when(mock(mockObject.method())).thenReturn(false);
reset(mockObject);
when(mock(mockObject.method())).thenReturn(true);

Workaround calling reset before next stubbing duplicate, but would be great be default simpler usage and does not reset the whole object.

Regards

Mock ngrx store

Hi guys, I trying use ts-mockito for mock ngrx store.

With "plain" selectors its works good:
when(storeMock.select(getCurrentTabId)).thenReturn(Observable.of('') as any);

But if selector with input params (like: getCardDetailsById('123')) then I have some problems with mock:
when(storeMock.select(getCardDetailsById('123'))).thenReturn(Observable.of({}) as any); - its doesn't work (test runs but failed because mock didn't triggered)

And sure, I can use anything(), but I have several test cases with this "problem" in one test, so can't use anything() and try find a way for solve it.

How to capture and return value?

I'm trying to do both a capture and return on the same mock, but I can't figure out how to set it up. This is my attempt so far:

const mockedDS = mock(MyDataService);
const whenCall = when(mockedDS.update(anything(), anything());
whenCall.thenReturn("OK");
const firstCaptor = new Captor<Array<Employee>>();
const secondCaptor = new Captor<TimePeriod>();
whenCall.thenCapture(firstCaptor, secondCaptor);

It seems that I can only do one or the other? Depending on whether I call thenCapture before thenReturn or vice versa it will only capture OR return the value.

Btw. What I'd really like to write is this;

const mockedDS = mock(MyDataService);
const firstCaptor = new Captor<Array<Employee>>();
const secondCaptor = new Captor<TimePeriod>();
when(mockedDS.update(anything(), anything())
    .thenCapture(firstCaptor, secondCaptor);
    .thenReturn("OK");

...but both thenReturn and thenCapture returns void

More Accurate Typing of Matchers

Hello all. Thank you for this library: it has made unit testing my Typescript code much much easier :).

I had a question about the types of the matchers. I recently made an interface-breaking change in my code, but my tests did not have the compilation errors I expected. The reason is that although ts-mockito will type check normal expectations, once I wrap it in a deepEqual matcher, the matcher returns an any. Here is a simplified example:

abstract class Area {
  public abstract toString(): string;
}

class ZipCode extends Area {
  constructor(private zipCode: string) { super(); }

  public toString() { return this.zipCode; }
}

class CityState extends Area {
  constructor(private city: string, private state: string) { super(); }

  public toString() { return `${this.city}, ${this.state}`; }
}

class WeatherClient {
  public getWeather(area: Area): Promise<string>;
}

const client = mock(WeatherClient);
when(client.getWeather(deepEqual('81547'))).thenReturn(Promise.resolve('rainy'));

I would expect the when line to throw a type error, because I'm passing in a string, but the deepEqual changes it to any.

The relevant line is here:
https://github.com/NagRock/ts-mockito/blob/master/src/ts-mockito.ts#L108

Is it possible to redefine deepEqual to something like:

export function deepEqual<T>(expected: T): T

?

Thank you!

Capturing method call arguments with separate API method

in #16 were proposed fluent API for capturing arguments and setting return value. But this API is in conflict with #12
So after conversation with @michalstocki we thought about such solutions:

  1. when(someObject.doSomething(anything())).thenReturn(3).thenCapture(captor); - but after implementing #12 this API would be illogical because we will be able to define more returning values with fluent API e.g. when(someObject.doSomething(anything())).thenReturn(3).thenReturn(4).thenReturn(5).thenCapture(captor); - thenReturn call order will have matter. So thenCapture does not fit here.
  2. verify(someObject.doSomething(captor.capture())); - similar to JavaMockito version, but we decided that using verify API function is not best solution, maybe this will be added as option to be more compatible with Java version
  3. when(someObject.doSomething(anything())).thenReturnAndCapture(3, captor) - this not looks nice, and arguments type checking will be impossible.
  4. when(someObject.doSomething(anything(firstCaptor))).thenReturn(3); - on first sight looks nice, but capturing arguments should not have any conditions while here we can define e.g. between(3, 4, capture) - and this looks bad
  5. capture(someObject.doSomething(captor)); - this looks best at all, we do not use conditions, we strictly says that we want to capture arguments

Doc for Basic looks to be incorrect.

The Basic example in the README shows:
let mockedFoo:Foo = mock(Foo);

but the the verify has:
verify(fooMock.getBar(3)).called();

fooMock is not defined.

@types/lodash should be a dev dependency or a peer dependency

Hey! First of all I want to thank you for the awesome Mocking Frameworks that you made.

In package.json @types/lodash is referenced as a direct dependency and its loaded automatically in the ts-mockito depended projects.

It wouldn't be a problem if everyone would use lodash but that's not the case. At the compile the variable _ enters in conflict with other libraries that define the same variable name.

Resulting in a nasty, not so easy to debug :

Error "Duplicate identifier '_'"

As the users of this framework use only the compiled .js with the typing definitions the @types/lodash is not required into dependencies.

Add verifiers `calledBefore` and `calledAfter`

It could be really nice to have a following verification options:

verify(classA.someMethod(someArg)).calledBefore(classB.someMethod(otherArg));
verify(classA.someMethod(someArg)).calledAfter(classB.someMethod(otherArg));

or maybe different syntax:

const classACall:(someType?) = verify(classB.someMethod(otherArg)).called();
verify(classA.someMethod(someArg)).calledBefore(classACall);

However I'd prefere the first syntax.

Module can't be bundled using rollup ("A module cannot import itself")

import * as mockito from "./ts-mockito";
export default mockito;

The ts-mockito module requires itself to export itself as default. I find this rather confusing, and it causes an error when bundling the module using rollup with rollup-plugin-commonjs ("A module cannot import itself
"). Isn't there are a cleaner solution to provide a default export?

Support for ES6 Proxy results in always new instances in instance() call

The instance() call for a mock returns always a new Proxy class instance (when supported). In that case e.g. a verify() does not recognise the parameter when an instance of a mock is used.

This is a different behaviour compared to the result of an instance() call when Proxy is not supported by the browser.

A simple (somehow constructed) example:

const fooMock = mock(Foo);
const fooInstance = instance(fooMock);

// ... some code later

when(fooMock.clone(instance(fooMock))).thenReturn(fooInstance); 
/*
the "when()" does not match because a new Proxy class will be
returned from "instance()" for each call (works in an older
browser not supporting Proxy)
*/
fooInstance.clone(fooInstance);

Although the example is quite constructed, the instance() method should not change its behaviour depending on the environment.

Support for getters/setters

It looks like getters and setters are not currently supported. Is there a plan for this in the future?

Example:

class LocationUtility {
    public get routeParams():  any {
         return {};
    }
}

The below code will result in an error: "Uncaught TypeError: Cannot read property 'proof' of undefined"

let location = mock(LocationUtility);
instance(location).routeParams.id 

Stubbing fields and returning string

first of all, great library! simple and powerful.

I just want to mock a class and return a string on a precise field, but I'm getting an error on a precise case.

I'm wondering if it's a bug or I'm doing it wrongly?

WORKING Sample code

export class DtoData {
    data: string;
}

const mockData = mock(DtoData );
when(mockData.data).thenReturn('test');

BREAKING Sample code because of the imGonnaBreakTheDto() method declared (but not used) in the class

export class DtoData {
    data: string;

    imGonnaBreakTheDto() {
        return this.data && this.data;
    }
}

const mockData = mock(DtoData );
when(mockData.data).thenReturn('test');

this gives me 'Cannot read property 'add' of undefined' on the when because it finds 'data' as function instead of MethodToStub type when using the thenReturn.

Funny thing is that if I use only

imGonnaBreakTheDto() {
   return this.data;
}

it works.

Mock static methods

Hi folks,

are there any plans to support mocking of static methods?

Cheers
Ingo

spy support

Hey guys,
Any plan on supporting spy in the same style as java mockito does? the library is fantastic by the way
Kind Regards
Gabriel

should not verify if missing arg

Great framework! I noticed though that verify doesn't properly seem to check for different number of arguments/missing arguments.

class Foo {
  bar(a?: number, b?: number) {}
}
let mockFoo = mock(Foo)
let foo = instance(mockFoo)
foo.bar(5)
verify(mockFoo.bar(5, 6)).called()

This should throw a verification error but doesn't.

Is it possible to mock an Observable?

Hi,

I really like ts-mockito, so thank you for this library. Following this guide on stubbing Observables in angular 2, it seemed straightforward to do a similar thing with mocks.

Consider a service with a method, getObservable(), that returns an Observable<SomeType>, where SomeType is simply a TS interface. How would one setup a mocked object to override this method?

First I created some mocked data of type SomeType:

const mockedData: SomeType = {foo: 'bar'}

And then I stub the method call

when(mockedService.getData('1')).thenReturn(Observable.of(mockedData))

But this gives a runtime error (compiler has no problem with it...)

TypeError: Cannot read property 'methodStubCollection' of null
    at http://localhost:9876/_karma_webpack_/webpack:/C:/Users/xbbl2q8/Desktop/development/ears-ui/ewh-earsui-angularui/node_modules/ts-mockito/lib/MethodStubSetter.js:18:1
    at Array.forEach (<anonymous>)
    at MethodStubSetter.webpackJsonp.../../../../ts-mockito/lib/MethodStubSetter.js.MethodStubSetter.thenReturn (http://localhost:9876/_karma_webpack_/webpack:/C:/Users/xbbl2q8/Desktop/development/ears-ui/ewh-earsui-angularui/node_modules/ts-mockito/lib/MethodStubSetter.js:17:1)
    at Object.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/C:/Users/xbbl2q8/Desktop/development/ears-ui/ewh-earsui-angularui/src/app/shared/services/activiti/activiti.handler.spec.ts:82:37)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/C:/Users/xbbl2q8/Desktop/development/ears-ui/ewh-earsui-angularui/node_modules/zone.js/dist/zone.js:392:1)
    at ProxyZoneSpec.webpackJsonp.../../../../zone.js/dist/proxy.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/C:/Users/xbbl2q8/Desktop/development/ears-ui/ewh-earsui-angularui/node_modules/zone.js/dist/proxy.js:79:1)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/C:/Users/xbbl2q8/Desktop/development/ears-ui/ewh-earsui-angularui/node_modules/zone.js/dist/zone.js:391:1)
    at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.run (http://localhost:9876/_karma_webpack_/webpack:/C:/Users/xbbl2q8/Desktop/development/ears-ui/ewh-earsui-angularui/node_modules/zone.js/dist/zone.js:142:1)
    at Object.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/C:/Users/xbbl2q8/Desktop/development/ears-ui/ewh-earsui-angularui/node_modules/zone.js/dist/jasmine-patch.js:104:1) 

Anyone ever seen something similar?

Also posted on SO (https://stackoverflow.com/questions/47035242/angular-observable-stubbing-doesnt-work-in-ts-mockito)

Dropping into the source, it looks like MethodStubSetter.js is not setting_this.methodStub when called via the Observable.of() method.

Mock of restify response is not working

When I try to create a mock of the Restify Response,

import { mock } from 'ts-mockito';
import { Response } from 'restify';

const response: Response = mock(Response);

I get the error:

Type 'Response' is not assignable to type 'Response'. Two different types with this name exist, but they are unrelated.
Property 'header' is missing in type 'Response'.

Is there any way to solve this issue?

thx

Mocking methods with optional parameters does not seem to work

import { instance, mock, when } from 'ts-mockito'
import expect from 'ceylon'

export default class TestClass {
    withOptionalParameter(foo: string, bar?: string) {
        return foo + bar
    }
}

describe('using a ts-mockito mock of TestClass ->', () => {
    const mockCreator = mock(TestClass)
    when(mockCreator.withOptionalParameter('a')).thenReturn('aa')
    when(mockCreator.withOptionalParameter('b', 'c')).thenReturn('bcbc')
    const mockInstance = instance(mockCreator)
    describe('withOptionalParameter', () => {
        it('should work!', () => {
            expect(mockInstance.withOptionalParameter('a')).toEqual('aa')
            expect(mockInstance.withOptionalParameter('b', 'c')).toEqual('bcbc')
        })
    })
})

This results in a "TypeError: Cannot read property 'match' of undefined" when running the test.

If the first when call is change to have two parameters like the second one, ie when(mockCreator.withOptionalParameter('a', 'a')).thenReturn('aa') then the test works. So apparently something goes wrong if you provide multiple when matchers with different numbers of parameters.

How to mock fields

Is it currently possible to mock field values? Unfortunately, not everything is using get and set functions and exposing the field instead.

export class Foo {
    isBar: boolean;
}    
let fooMock = mock(Foo);
when(fooMock.isBar).thenReturn(false);

throws the error:

TypeError: Cannot read property 'methodStubCollection' of undefined
at MethodStubSetter.thenReturn (webpack:/~/ts-mockito/lib/MethodStubSetter.js:18:1)
at Object. (webpack:/fooTests.ts:25:33)

Is there a cool way without using:

let inst = instance(fooMock);
inst.isBar = false;

??
If not, are you open for a pull request with an suggestion?
If yes does it have to be similar to the java mockito way of doing it (if there is one)?

Verifiers don't work correctly with inherited logic

I have the following inheritance:

abstract class A {
  protected protectedField:SomeType;

  public setProtected(type:SomeType):void {
    this.protectedField = type;
  }
}

class B extends A {
  public someMethod():void {
    this.protectedField.doSomething();
  }
}

And I try to test:

it('does something', () => {
  // given
  const mockType:SomeType = mock(SomeType);
  const b = new B();
  b.setProtected(instance(mockType));

  // when
  b.someMethod();

  // then
  verify(mockType.doSomething()).once();
});

Then I unfortunatelly get the following error:

Expected "doSomething()" to be called 1 time(s). But has been called 0 time(s).
	times
	once

Why the `reset` function doesn't reset the mock configuration?

When I can see the reset function, I expect them to reset not only the calls which were recorded, but also the mocked functionality of all the methods.

I expect the following test to pass:

describe('Mock resetting', () => {
    it('should reset a value configured to be returned', () => {
        // given
        const myClassMock = mock(MyClass);
        when(myClassMock.methodB('some string')).thenReturn('other string');
        const myClass = instance(myClassMock);
        reset(myClassMock);

        // when
        const result = myClass.methodB('some string');

        // then
        expect(result).to.not.equal('other string');
    });
});

class MyClass {

    public methodB(someArgument:string):string {
        return `provided value: ${someArgument}`;
    }
}

Here is a link for the test within the configured project:
https://github.com/michalstocki/ts-mockito-example/blob/master/test/spec/extension/resetting/mock-resetting.spec.ts

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.