{"action":"created","issue":{"url":"https://api.github.com/repos/inversify/InversifyJS/issues/197","repository_url":"https://api.github.com/repos/inversify/InversifyJS","labels_url":"https://api.github.com/repos/inversify/InversifyJS/issues/197/labels{/name}","comments_url":"https://api.github.com/repos/inversify/InversifyJS/issues/197/comments","events_url":"https://api.github.com/repos/inversify/InversifyJS/issues/197/events","html_url":"https://github.com/inversify/InversifyJS/issues/197","id":154085749,"number":197,"title":"Discussion: InversifyJS testing utils","user":{"login":"remojansen","id":10656223,"avatar_url":"https://avatars.githubusercontent.com/u/10656223?v=3","gravatar_id":"","url":"https://api.github.com/users/remojansen","html_url":"https://github.com/remojansen","followers_url":"https://api.github.com/users/remojansen/followers","following_url":"https://api.github.com/users/remojansen/following{/other_user}","gists_url":"https://api.github.com/users/remojansen/gists{/gist_id}","starred_url":"https://api.github.com/users/remojansen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/remojansen/subscriptions","organizations_url":"https://api.github.com/users/remojansen/orgs","repos_url":"https://api.github.com/users/remojansen/repos","events_url":"https://api.github.com/users/remojansen/events{/privacy}","received_events_url":"https://api.github.com/users/remojansen/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/inversify/InversifyJS/labels/discussion","name":"discussion","color":"eb6420"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-05-10T19:21:32Z","updated_at":"2016-05-12T07:58:54Z","closed_at":null,"body":"@otbe asked me to implement some decorators to help during unit testing. This is really interesting and I believe that there are a lot of things that we can use to improve the developers testing experience.\r\n\r\nMy plan is to develop an stand alone npm package. It will contain some testing utils.\r\n\r\nThe initial request refers to decorators like `@mock` and `@mockSingleton`:\r\n\r\n```ts\r\nexport function mock<Interface> (binding: string|Symbol|INewable<Interface>) {\r\n  return (targetClass: INewable<Interface>): void => {\r\n    injectable()(targetClass);\r\n    kernel.unbind(binding);\r\n    kernel.bind(binding).to(targetClass);\r\n  }\r\n}\r\n\r\n@mock(MyService)\r\nclass MyServiceMock {\r\n  name:string = 'foo';\r\n}\r\n```\r\n\r\n```ts \r\nfunction mockSingleton<Interface> (binding: string|Symbol|INewable<Interface>) {\r\n  return (targetClass: INewable<Interface>): void => {\r\n    kernel.unbind(binding);\r\n    kernel.bind(binding).toConstantValue(new targetClass);\r\n  }\r\n}\r\n```\r\n\r\nI'm creating this issue to keep track of all the requests and ideas. \r\n\r\nIf you want to suggest something please add a comment or [join us on Gitter](https://gitter.im/inversify/InversifyJS). I will collect the feedback from the chat and add it here..."},"comment":{"url":"https://api.github.com/repos/inversify/InversifyJS/issues/comments/218686430","html_url":"https://github.com/inversify/InversifyJS/issues/197#issuecomment-218686430","issue_url":"https://api.github.com/repos/inversify/InversifyJS/issues/197","id":218686430,"user":{"login":"otbe","id":3391052,"avatar_url":"https://avatars.githubusercontent.com/u/3391052?v=3","gravatar_id":"","url":"https://api.github.com/users/otbe","html_url":"https://github.com/otbe","followers_url":"https://api.github.com/users/otbe/followers","following_url":"https://api.github.com/users/otbe/following{/other_user}","gists_url":"https://api.github.com/users/otbe/gists{/gist_id}","starred_url":"https://api.github.com/users/otbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/otbe/subscriptions","organizations_url":"https://api.github.com/users/otbe/orgs","repos_url":"https://api.github.com/users/otbe/repos","events_url":"https://api.github.com/users/otbe/events{/privacy}","received_events_url":"https://api.github.com/users/otbe/received_events","type":"User","site_admin":false},"created_at":"2016-05-12T07:58:54Z","updated_at":"2016-05-12T07:58:54Z","body":"After some time using ```@mock``` Im not that happy with it :/ I want to share my mocks across several tests and if I do one time:\r\n\r\n```javascript\r\n@mock(MyService)\r\nexport class MyServiceMock {\r\n  foo(): number {\r\n    return;\r\n  }\r\n}\r\n```\r\n\r\n```MyService``` is mocked for every test, because my kernel is shared too. That may be fine for services that use ```MyService```, but if I test ```MyService``` itself I have to unbind the mock. So at the end I have to ensure that I get the correct version (mocked or not mocked) of ```MyService``` in every test. But a bigger problem is, that I have to ```kernel.get(MyService)``` in ```beforeEach``` for getting an instance of this mock, because I want to spy on it and modify the behavior of methods.\r\n\r\nIm switched to something like that:\r\n```javascript\r\nexport function setupSingletonMock<T>(target: string | Symbol | INewable<any>, mock: { new(...args: any[]): T; }): T {\r\n  kernel.unbind(target);\r\n  kernel.bind<T>(target).to(mock).inSingletonScope();\r\n  return kernel.get<T>(target);\r\n}\r\n```\r\n\r\nand use it like \r\n\r\n```javascript\r\nlet myServiceMock;\r\nbeforeEach(() => {\r\n   myServiceMock = setupSingletonMock(MyService, MyServiceMock);\r\n});\r\n\r\nit('test', () => {\r\n  spyOn(myServiceMock, 'foo').andReturn(5);\r\n});\r\n```\r\n\r\nWhat do you think about it?\r\n\r\n\r\n"}}