You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+28-28Lines changed: 28 additions & 28 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -519,25 +519,25 @@ Check out documentation for [inversify-vanillajs-helpers](https://github.com/inv
519
519
520
520
#### @LazyInject decorator
521
521
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:
`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:
534
534
535
535
```js
536
536
import { LazyInject } from'./di';
537
537
import { AUTH_SERVICE_ID } from'./services/auth';
538
538
539
539
classLoginViewextendsVue {
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
541
541
542
542
login (username, password) {
543
543
returnthis.authService.login(username, password);
@@ -551,7 +551,7 @@ class LoginView extends Vue {
551
551
552
552
#### 1. Mocking behavior in development
553
553
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:
555
555
556
556
```js
557
557
classRealEmailService {
@@ -579,7 +579,7 @@ if (process.env.NODE_ENV === "production") {
579
579
@Register("orderService", ["emailService"])
580
580
classOrderService {
581
581
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
583
583
}
584
584
585
585
registerOrder(order) {
@@ -630,7 +630,7 @@ Replacing registered classes allows you to control dependencies of the service u
630
630
631
631
#### Mocking service dependencies
632
632
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:
634
634
635
635
```js
636
636
classServiceA {
@@ -672,41 +672,41 @@ describe('Service A', function () {
672
672
673
673
A couple of issues here:
674
674
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.
677
677
678
678
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.
679
679
680
680
```js
681
681
describe('Service A', function () {
682
682
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
+
constserviceD= {}; // instead of using real ServiceD constructor, create an empty object and fake all methods that are used from serviceA
684
684
serviceD.doSomething=sinon.spy();
685
685
this.serviceDMock= serviceD;
686
686
687
-
let serviceE =newServiceE(serviceD);
688
-
let serviceB =newServiceB(serviceD);
689
-
let serviceC =newServiceC(serviceE);
690
-
let serviceA =newServiceA(serviceB, serviceC);
687
+
constserviceE=newServiceE(serviceD);
688
+
constserviceB=newServiceB(serviceD);
689
+
constserviceC=newServiceC(serviceE);
690
+
constserviceA=newServiceA(serviceB, serviceC);
691
691
692
692
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.
693
693
});
694
694
695
695
afterEach(function () {
696
-
this.serviceBMock.verify(); // verify all expectations have been called
696
+
this.serviceBMock.verify(); // verify if all expectations have been called
697
697
});
698
698
699
699
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
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.
710
710
711
711
```js
712
712
import { Register } from'./di';
@@ -735,45 +735,45 @@ class ServiceE {
735
735
}
736
736
```
737
737
738
-
... and then in spec file you can just type
738
+
... and then in the spec file you can just type:
739
739
740
740
```js
741
741
importcontainerfrom'./di';
742
742
743
743
describe('Service A', function () {
744
744
beforeEach(function () {
745
-
let serviceA =container.get('serviceA');
745
+
constserviceA=container.get('serviceA');
746
746
});
747
747
});
748
748
```
749
749
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.
751
751
752
752
```js
753
753
importcontainerfrom'./di';
754
754
755
755
describe('Service A', function () {
756
756
beforeEach(function () {
757
-
let serviceC =container.get('serviceC');
757
+
constserviceC=container.get('serviceC');
758
758
this.serviceCMock=sinon.mock(serviceC);
759
759
container.rebind('serviceC').toConstantValue(serviceC); // removes old registered class and replaces it with singleton constant value
760
-
let serviceA =container.get('serviceA');
760
+
constserviceA=container.get('serviceA');
761
761
});
762
762
763
763
afterEach(function () {
764
764
this.serviceCMock.verify(); // verify all expectations have been called
765
765
});
766
766
767
767
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
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.
777
777
778
778
```js
779
779
importcontainerfrom'./di';
@@ -816,7 +816,7 @@ afterEach(function () {
816
816
}
817
817
```
818
818
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.
0 commit comments