allenhwkim / ngentest

Angular6+ Unit Test Generator For Components, Directive, Services, and Pipes
https://ngentest.github.io
MIT License
144 stars 60 forks source link

Invalid data type for services #30

Closed t0n1n3 closed 4 years ago

t0n1n3 commented 4 years ago

Hi,

Many times my services inject other services in the constructor. The template assign them as an object '{}' which throws the error Argument of type '{}' is not assignable to parameter of type "serviceName".

Sample service.ts

export class DataService {
     constructor(private http: HttpClient) { }
}

Sample spec file generated

beforeEach(() => {
    service = new DataService({}); // ERROR: Argument of type '{}' is not assignable to parameter of type 'HttpClient'.
// Type '{}' is missing the following properties from type 'HttpClient': handler, request, delete, get, and 6 more.
});
allenhwkim commented 4 years ago

Sorry for the late response. Please provide your test .ts file and your command output. I think you are missing something related to mock.

t0n1n3 commented 4 years ago

Command - ngentest data.service.ts

data.service.ts

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';

@Injectable()
export class DataService {

  constructor(private _router: Router) {
  }

}

data.service.spec.ts

import { async } from '@angular/core/testing';
import { Injectable } from '@angular/core';
import { Observable, of as observableOf, throwError } from 'rxjs';

import { DataService } from './menu.service';
import { Router } from '@angular/router';

@Injectable()
class MockRouter {
  navigate() {};
}

describe('DataService', () => {
  let service;

  beforeEach(() => {
    service = new DataService({});  // ERROR: Argument of type '{}' is not assignable to parameter of type 'Router'. Type '{}' is missing the following properties from type 'Router': rootComponentType, urlSerializer, rootContexts, location, and 48 more.
  });

});
allenhwkim commented 4 years ago

This is working for me. if this is from your Typescript checking, please make the type checking loose for your .spec files

$ cat ./data.service.ts
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';

@Injectable()
export class DataService {

  constructor(private _router: Router) {
  }

  test() {
    this.foo = 1;
  }

}
$ cat ./data.service.spec.ts
import { async } from '@angular/core/testing';
import { Injectable } from '@angular/core';
import { Observable, of as observableOf, throwError } from 'rxjs';

import { DataService } from './data.service';
import { Router } from '@angular/router';

@Injectable()
class MockRouter {
  navigate = jest.fn();
}

describe('DataService', () => {
  let service;

  beforeEach(() => {
    service = new DataService({});
  });

  it('should run #test()', async () => {

    service.test();

  });

});
$ jest ./data.service.spec.ts
 PASS  ./data.service.spec.ts
  DataService
    ✓ should run #test() (2ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.382s, estimated 4s
Ran all test suites matching /.\/data.service.spec.ts/i.
jest-html-reporter >> Report generated (./reports/unit-test-report/index.html)
t0n1n3 commented 4 years ago

Hi,

After adding the line // @ts-ignore above the error line seems to make the error go away and makes the test runs smoothly.

Also, can you test it in Karma once?

Thanks.

allenhwkim commented 4 years ago

This is tsconfig.json example to ignore spec files.

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@angular/*": [
        "./node_modules/@angular/*"
      ],
      "test/*": [
        "test/*"
      ]
    },
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "allowJs": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom"
    ]
  },
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ],
  "preset": "ts-jest"
}

By adding exclude block, you can simply ignore all .spec typescript checking.

  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ],

Regarding Karma, I cannot provide test now.

t0n1n3 commented 4 years ago

Thanks for the resolution, It is working fine.