Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bb3021d

Browse files
committed
@LazyInject decorator through Mocking global objects
1 parent be6a51c commit bb3021d

File tree

1 file changed

+28
-28
lines changed

1 file changed

+28
-28
lines changed

‎README.md‎

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -519,25 +519,25 @@ Check out documentation for [inversify-vanillajs-helpers](https://github.com/inv
519519

520520
#### @LazyInject decorator
521521

522-
The LazyInject decorator can be very useful for injecting services into the VUE components. Because we don't have control over instantiating of the component, we need to inject services into properties. Let's import the decorator from [inversify-inject-decorators](https://github.com/inversify/inversify-inject-decorators) and make it available in `di.js` first:
522+
The LazyInject decorator can be very useful for injecting services into the VUE components, as we don't have control over the component instantiation we need to inject services into properties. Let's import the decorator from [inversify-inject-decorators](https://github.com/inversify/inversify-inject-decorators) and make it available in `di.js` first:
523523

524524
```js
525525
import getDecorators from 'inversify-inject-decorators';
526526

527-
let container = new Container();
528-
let { lazyInject } = getDecorators(container);
527+
const container = new Container();
528+
const { lazyInject } = getDecorators(container);
529529

530530
export { lazyInject as LazyInject }
531531
```
532532

533-
`di.js` creates new decorator LazyInject which is tied with the container where everything is registered. Now we can adjust code in VUE component:
533+
`di.js` creates a new decorator LazyInject which is tied with the container where everything is registered. Now we can adjust the code in the VUE component:
534534

535535
```js
536536
import { LazyInject } from './di';
537537
import { AUTH_SERVICE_ID } from './services/auth';
538538

539539
class LoginView extends Vue {
540-
@LazyInject(AUTH_SERVICE_ID) authService; // internally asks the container to get instance of the AUTH_SERVICE_ID
540+
@LazyInject(AUTH_SERVICE_ID) authService; // internally asks the container to get an instance of the AUTH_SERVICE_ID
541541

542542
login (username, password) {
543543
return this.authService.login(username, password);
@@ -551,7 +551,7 @@ class LoginView extends Vue {
551551

552552
#### 1. Mocking behavior in development
553553

554-
Let's say that you have an email service which sends emails to given address, but you don't want to send real emails in DEV/TEST/UAT environments. You can create two different implementations of the same interface and register them conditionally:
554+
Let's say that you have an email service which sends emails to a given address, but you don't want to send real emails in DEV/TEST environments. You can create two different implementations of the same interface and register them conditionally:
555555

556556
```js
557557
class RealEmailService {
@@ -579,7 +579,7 @@ if (process.env.NODE_ENV === "production") {
579579
@Register("orderService", ["emailService"])
580580
class OrderService {
581581
constructor(emailService) {
582-
this.emailService = emailService; // this would be real implementation in production, but fake in other environments
582+
this.emailService = emailService; // this would be a real implementation in production, but fake in other environments
583583
}
584584

585585
registerOrder(order) {
@@ -630,7 +630,7 @@ Replacing registered classes allows you to control dependencies of the service u
630630

631631
#### Mocking service dependencies
632632

633-
Let's have a service which depends on other services. Before we even start writing tests, make sure that the dependency is really needed. Huge dependency trees are always hard to test and hard to maintain because of the complexity. You can try to decouple the services and separate their logic. If it's not possible, then you should always mock other services out. Consider following services:
633+
Let's have a service which depends on other services. Before we even start writing tests, make sure that the dependency is really needed. Huge dependency trees are always hard to test and hard to maintain because of the complexity. You can try to decouple the services and separate their logic. If it's not possible, then you should always mock other services out. Consider the following services:
634634

635635
```js
636636
class ServiceA {
@@ -672,41 +672,41 @@ describe('Service A', function () {
672672

673673
A couple of issues here:
674674

675-
1. You have to be aware of service instantiation order, `serviceD` must be created before `serviceE` and `serviceB`, `serviceE` before `serviceC` and once you have all dependencies ready, you can finally call the constructor of `ServiceA`. If dependency tree changes, you have to adjust all tests.
676-
1. Every time new service is added to the tree, you have to update the tests too.
675+
1. You have to be aware of the service instantiation order, `serviceD` must be created before `serviceE` and `serviceB`, `serviceE` before `serviceC` and once you have all dependencies ready, you can finally call the constructor of `ServiceA`. If the dependency tree changes, you have to adjust all tests.
676+
2. Every time a new service is added to the tree, you have to update the tests too.
677677

678678
When you want to mock any service in the tree, consider using a fake object with stub methods instead of calling a real constructor. If you are using [sinon](https://www.npmjs.com/package/sinon), check out their [mock API](http://sinonjs.org/releases/v4.5.0/mocks/) which enables lots of nice features and gives you better control over your mocked services.
679679

680680
```js
681681
describe('Service A', function () {
682682
beforeEach(function () {
683-
let serviceD = {}; // instead of using real ServiceD constructor, create an empty object and fake all methods that are used from serviceA
683+
const serviceD = {}; // instead of using real ServiceD constructor, create an empty object and fake all methods that are used from serviceA
684684
serviceD.doSomething = sinon.spy();
685685
this.serviceDMock = serviceD;
686686

687-
let serviceE = new ServiceE(serviceD);
688-
let serviceB = new ServiceB(serviceD);
689-
let serviceC = new ServiceC(serviceE);
690-
let serviceA = new ServiceA(serviceB, serviceC);
687+
const serviceE = new ServiceE(serviceD);
688+
const serviceB = new ServiceB(serviceD);
689+
const serviceC = new ServiceC(serviceE);
690+
const serviceA = new ServiceA(serviceB, serviceC);
691691

692692
this.serviceBMock = sinon.mock(serviceB); // mock serviceB using sinon.mock API. this will create Proxy object which you can configure to expect calls on serviceB instance.
693693
});
694694

695695
afterEach(function () {
696-
this.serviceBMock.verify(); // verify all expectations have been called
696+
this.serviceBMock.verify(); // verify if all expectations have been called
697697
});
698698

699699
it('should do something', function () {
700-
let doSomethingSpy = this.serviceBMock.expects('doSomething').returns(42).once();
701-
let result = serviceA.runMethodUnderTest(24); // let's assume that this method calls serviceB and serviceD
700+
const doSomethingSpy = this.serviceBMock.expects('doSomething').returns(42).once();
701+
const result = serviceA.runMethodUnderTest(24); // let's assume that this method calls serviceB and serviceD
702702
expect(result).to.equal(66);
703703
expect(doSomethingSpy).to.have.been.calledWith(24);
704704
expect(this.serviceDMock.doSomething).to.have.been.calledWith(24);
705705
});
706706
});
707707
```
708708

709-
Now, let's do better approach and let DI container to resolve our dependencies.
709+
Now, let's do a better approach and let the DI container to resolve our dependencies.
710710

711711
```js
712712
import { Register } from './di';
@@ -735,45 +735,45 @@ class ServiceE {
735735
}
736736
```
737737

738-
... and then in spec file you can just type
738+
... and then in the spec file you can just type:
739739

740740
```js
741741
import container from './di';
742742

743743
describe('Service A', function () {
744744
beforeEach(function () {
745-
let serviceA = container.get('serviceA');
745+
const serviceA = container.get('serviceA');
746746
});
747747
});
748748
```
749749

750-
It's much nicer now, but wait, the mocking ability is now gone. How `serviceC` can be mocked during execution of these tests? The service registration in DI container can be replaced with our own mock.
750+
It's much cleaner now, but wait, the mocking ability is now gone. How `serviceC` can be mocked during execution of these tests? The answer to that is simple, the service registration in the DI container can be replaced with our own mock.
751751

752752
```js
753753
import container from './di';
754754

755755
describe('Service A', function () {
756756
beforeEach(function () {
757-
let serviceC = container.get('serviceC');
757+
const serviceC = container.get('serviceC');
758758
this.serviceCMock = sinon.mock(serviceC);
759759
container.rebind('serviceC').toConstantValue(serviceC); // removes old registered class and replaces it with singleton constant value
760-
let serviceA = container.get('serviceA');
760+
const serviceA = container.get('serviceA');
761761
});
762762

763763
afterEach(function () {
764764
this.serviceCMock.verify(); // verify all expectations have been called
765765
});
766766

767767
it('should do something', function () {
768-
let doSomethingSpy = this.serviceCMock.expects('doSomething').returns(42).once();
769-
let result = serviceA.runMethodUnderTest(24); // let's assume that this method calls serviceC
768+
const doSomethingSpy = this.serviceCMock.expects('doSomething').returns(42).once();
769+
const result = serviceA.runMethodUnderTest(24); // let's assume that this method calls serviceC
770770
expect(result).to.equal(66);
771771
expect(doSomethingSpy).to.have.been.calledWith(24);
772772
});
773773
});
774774
```
775775

776-
Everything that test changes in the container registration should be restored after the test is done, otherwise changes might affect the following test. You can achieve this by using built-in functionality in inversify called [snapshots](https://github.com/inversify/InversifyJS/blob/master/wiki/container_snapshots.md). Create a snapshot before you perform changes to registration and restore it back to normal after your test is done.
776+
Everything that the test changes in the container registration should be restored after the test is done, otherwise changes might affect the next test execution. You can achieve this by using the built-in functionality in the inversify package called [snapshots](https://github.com/inversify/InversifyJS/blob/master/wiki/container_snapshots.md). Create a snapshot before you perform changes to registration and restore it back to normal after your test is done.
777777

778778
```js
779779
import container from './di';
@@ -816,7 +816,7 @@ afterEach(function () {
816816
}
817817
```
818818

819-
If you are using `--watch` mode, files included are not executed after any change, so the better solution is to import this file at the top of your spec file instead.
819+
If you are using `--watch` mode, files included with the flag `--include`are not hot reloaded after changing it's content, to overcome this problem, the solution is to import the file at the top of your spec file.
820820

821821
#### Mocking global objects
822822

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /