Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot read property 'MobileServiceClient' of undefined Testing

I am trying to test my component that has a constructor that has injected a service called AzureService

Here is the component snippet:

constructor(private azureService: AzureService) { }

Here is the spec file:

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        DashbaordComponent,
        StatusComponent
      ],
      providers:[ AzureService]
    }).compileComponents();
  }));

  it('should create the app', async(() => {
    const fixture = TestBed.createComponent(DashbaordComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  }));

Here is the service:

export declare var WindowsAzure;
@Injectable()
export class AzureService {
constructor() { this.client = new WindowsAzure.MobileServiceClient(this.azureUrl); }
}

I am unable to understand why it is not important Azure-Apps-Client library that is imported in index.html file:

<script src="//zumo.blob.core.windows.net/sdk/azure-mobile-apps-client.2.0.0.js"></script>

Is there a way i can load this library before i run the test?

Any lead to this?

UPDATE: Here is the reason of test-failure: enter image description here

UPDATE: Here is the component code:

  getModules() {
        this.result.updateInfo("Getting classes...")

        this.azureService.getProgrammesByWrapper().then(((res) => {
            this.result.updateInfo("Sorting classes...")
            this.displayModules(res);
            this.result.updateSuccess(true);
        }));
    }
like image 206
User1911 Avatar asked Jun 20 '17 10:06

User1911


2 Answers

A recommended approach by Google, rather than using the actual service, is to use a test-double for unit testing components. While it seems to make sense to load in your required libraries, a unit test should really only be focused on testing your component code.

A component-under-test doesn't have to be injected with real services. In fact, it is usually better if they are test doubles (stubs, fakes, spies, or mocks). The purpose of the spec is to test the component, not the service, and real services can be trouble.

To create a test-double stub of the service, define a plain old javascript object in your .spec file that contains the required functions or properties for the component to work in this context, like so:

const exampleServiceStub = {
  getProgrammesByWrapper(): Promise<Module[]> {
    return Promise.resolve([
      { id: 1, title: "Test Module 1", description: "Example description." },
      { id: 2, title: "Test Module 2", description: "Example description." }
    ]);
  }
}

You can configure your test-double to test the exact state of the service that you would like, or manipulate it later. Then list your test-double service as a provider to stand in place of your real service:

TestBed.configureTestingModule({
   declarations: [ ExampleComponent ],
   providers:    [ {provide: ExampleService, useValue: exampleServiceStub } ]
});

If you need to refer to your service in your test, make sure you get it from the injector.

Update: You can check the example I put together on Github demonstrating this: component / service / test with a mock service.

Good luck!

like image 129
SpaceFozzy Avatar answered Nov 20 '22 12:11

SpaceFozzy


If you really need to use that service, try the following approaches. If not, try what @SpaceFozzy have suggested.


Approach #1 (If you use angular-cli)

specify the scripts with

//...
"app": {
  //...
  "scritps": ["//zumo.blob.core.windows.net/sdk/azure-mobile-apps-client.2.0.0.js"]
  //...
}
//...

update 1:

The above is in valid. It turns out that the scripts config is not for scripts from network, but for local script.

If you don't want to require the script like the Approach #2, you can still install it, but refer it from the scripts. like:

//...
"app": {
  //...
  "scritps": ["node_modules/azure-mobile-apps-client/path_to_script_you_want"]
  //...
}
//...

It may be necessary when someone need to use script tag to refer the cdn-version script on production site.

reference: https://github.com/angular/angular-cli/wiki/stories-global-scripts

Approach #2

you can install azure-mobile-apps-client via npm. https://www.npmjs.com/package/azure-mobile-apps-client

Then require it wherever you need it:

var WindowsAzure = require('azure-mobile-apps-client');
// Create a reference to the Azure App Service
var clientRef = new WindowsAzure.MobileServiceClient('https://YOUR-SITE-NAME.azurewebsites.net');

Your WindowsAzure won't be undefined.

like image 32
e-cloud Avatar answered Nov 20 '22 10:11

e-cloud