Angular-cli: Adding param to environment.ts fails during unit tests

Created on 22 Jul 2016  路  21Comments  路  Source: angular/angular-cli

I tried to add my backend url to environment.[dev|prod].ts as explain in README.md

src/environment.ts and config/environment.dev.ts (same content)

export const environment = {
  production: false,
  backend: {
    url: 'http://localhost:8080/api'
  }
};

config/environment.prod.ts

export const environment = {
  production: true,
  backend: {
    url: '/myapp/api'
  }
};

src/app/shared/profile-info.service.ts

import { Injectable }   from '@angular/core';
import { Http }         from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { ProfileInfo }  from './profile-info.model';
import { environment }  from '../../app';

@Injectable()
export class ProfileInfoService {
  constructor(private http: Http) {}
  getProfileInfo(): Promise<ProfileInfo> {
    return this.http.get(environment.backend.url + '/profile-info')
               .toPromise()
               .then(response => response.json())
               .catch(this.handleError);
  }
  private handleError(error: any) {
    console.error('An error occurred', error);
    return Promise.reject(error.message || error);
  }
}

At runtime

ng serve or ng serve -prod works fine BUT...

Unit test fails

>ng test --watch false
Built project successfully. Stored in "dist/".
22 07 2016 14:32:55.601:INFO [karma]: Karma v0.13.22 server started at http://localhost:9876/
22 07 2016 14:32:55.612:INFO [launcher]: Starting browser PhantomJS
22 07 2016 14:32:57.102:INFO [PhantomJS 2.1.1 (Windows 7 0.0.0)]: Connected on socket /#oYsAdh6c6MnyuUvFAAAA with id 25522896
PhantomJS 2.1.1 (Windows 7 0.0.0) Contract Service should ... FAILED
        Error: Cannot resolve all parameters for 'AppComponent'(undefined). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AppComponent' is decorated with Injectable. (line 233)
PhantomJS 2.1.1 (Windows 7 0.0.0) ProfileInfo Service should ... FAILED
        Error: Cannot resolve all parameters for 'AppComponent'(undefined). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AppComponent' is decorated with Injectable. (line 233)
PhantomJS 2.1.1 (Windows 7 0.0.0) App: CromeFront should create the app FAILED
        Error: Cannot resolve all parameters for 'AppComponent'(undefined). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AppComponent' is decorated with Injectable. (line 233)
PhantomJS 2.1.1 (Windows 7 0.0.0) App: CromeFront should have as title 'CROME' FAILED
        Error: Cannot resolve all parameters for 'AppComponent'(undefined). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'AppComponent' is decorated with Injectable. (line 233)
PhantomJS 2.1.1 (Windows 7 0.0.0): Executed 11 of 11 (4 FAILED) (0.021 secs / 0.022 secs)

What did I do wrong ?

Workaround

import { isDevMode } from '@angular/core';
...

@Injectable()
export class ProfileInfoService {
  private url: string;

  constructor(private http: Http) {}

  getProfileInfo(): Promise<ProfileInfo> {
    if(isDevMode()) {
      this.url = 'http://localhost:8080/api';
     } else {
       this.url = '/cromeApi/api';
    }
    return this.http.get(this.url + '/profile-info')
               .toPromise()
               .then(response => response.json())
               .catch(this.handleError);
  }
  private handleError(error: any) {
    console.error('An error occurred', error);
    return Promise.reject(error.message || error);
  }
}

Version

C:\tmp\myapp>ng --version
angular-cli: 1.0.0-beta.8
node: 6.2.1
os: win32 x64
2 (required) bufix

Most helpful comment

I am missing something because its still not possible to add and env variable to ng test on prompt

All 21 comments

Can you also show me your unit test?

sure: src/app/shared/profile-info.service.spec.ts

/* tslint:disable:no-unused-variable */

import {
  beforeEach, beforeEachProviders,
  describe, xdescribe,
  expect, it, xit,
  async, inject
} from '@angular/core/testing';
import { ProfileInfoService } from './profile-info.service';

describe('ProfileInfo Service', () => {
  beforeEachProviders(() => [ProfileInfoService]);

  it('should ...',
      inject([ProfileInfoService], (service: ProfileInfoService) => {
    expect(service).toBeTruthy();
  }));
});

Sorry, I should have been more specific. Can you show me your failing ones?

Actually this is one of failing ones:p
There's are default test generated by angular-cli
If I just add the environment values and use it in the service; the unit tests start fail ?!

See error log:
PhantomJS 2.1.1 (Windows 7 0.0.0) ProfileInfo Service should ... FAILED
Error: Cannot resolve all parameters for 'AppComponent'(undefined).

Generally speaking, whenever you change in your classes the generated unit tests should immediately fail.

I think I see at least part of what's going wrong here... It's weird that your ProfileInfo test fails showing a message about AppComponent, right? And you say it happens only if you add import { environment } from '../../app';?

I know that ../../app also exports AppComponent, but have no idea how it gets inserted into your tests. If you can get me a repo that I can debug, I might be able to find you an answer.

I am experiencing this same thing. The moment I try to use environment.foo within a service the component can no longer resolve the parameter for that service.

Also the failure happens when I try to mock with provide(Api, { useValue: {} }). The moment I remove the line that references environment the tests start passing again.

@filipesilva This is the bug reproduced from a angular-cli this happens on webpack-beta 1 and 2. Not sure about the broccoli version. It's making it impossible for us to test and deploy to production with confidence.

https://github.com/NorthernLogic/ng2-cli-environment-test-bug/commit/5c8a1e2937c816abf8ca817660d1a918e20a8c06~~ (I got the bug reproduction wrong, forgot to add the service to the test, I'll submit a new one shortly.)

Confirmed on the beta-10 as well. Oddly enough the app still compiles and runs. It seems to be specific to testing.

Finally! So after almost driving myself crazy I believe I have gotten to the bottom of this. It has to do with the spec file import order. The commit posted below demonstrates the issue. The prior commit has a spec file test.service.spec.ts and I renamed that to api.service.spec.ts. Just doing that caused the tests to go from pass to fail. I then renamed it to app.service.spec.ts (so it would come after app.component.ts) and the tests started to pass again.

I'm not sure of the actual solution but at least I have a workaround for now.

https://github.com/NorthernLogic/ng2-cli-environment-test-bug/commit/e02da5eccf12c76b28f18ea83702c605b47e003f

We're overhauling the app build process so I'm not sure this bug still exists. I you try the latest webpack release please? Instructions can be found here: https://github.com/angular/angular-cli#webpack-preview-release-update

Now that I think about it, there's no environment.ts replacement functionality in test builds overall... I think it should at least default to dev myself. I should add that.

@filipesilva as I mentioned I tested this using webpack.beta.2 which was the latest release when you made the comment.

See my comment above https://github.com/angular/angular-cli/issues/1419#issuecomment-239856955 that talks about the issue only manifesting when a certain lexical file name ordering exists.

I updated to 1.0.0-beta.11-webpack.8 and this still exists.

This is next on my list of stuff to fix.

@adamduren I tried to repro on the latest master yesterday (which is basically webpack.8) and after updating your example to use NgModules I couldn't repro the problem. You mentioned you had used webpack.8 to repro, was that with NgModules?

(reopened because PR was only a partial fix)

Closing as I think this has been fixed since. Let me know if it still happens and I'll reopen.

I am missing something because its still not possible to add and env variable to ng test on prompt

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NCC1701M picture NCC1701M  路  3Comments

MateenKadwaikar picture MateenKadwaikar  路  3Comments

hartjo picture hartjo  路  3Comments

brtnshrdr picture brtnshrdr  路  3Comments

rwillmer picture rwillmer  路  3Comments