使用 jasmine 和 angular 对基础 class 进行单元测试
Unit testing of base class with jasmine and angular
我有一个在每个网格组件中使用的通用基础 class。
现在,我有网格组件的规范,但我想在单独的基本规范文件中添加基本 class 的规范。
其背后的动机是删除重复代码并为基础网格制作通用规范文件,该文件将为每个使用基础的网格提供服务class。
我卡在了一点,我无法在基本规范文件中创建规范。基本上我希望基础文件中的所有规范都在一个函数下,当这个函数从子 class 调用该组件时,它应该 return 那个 class.[=50 的所有规范=]
Here is what I have and what I tried so far.
组件层:
export class MyComponent extends BaseGrid<MyEntity> {
... (and all other code like constructor and methods)...
}
基础层:
export class BaseGrid<T> {
public async getData(): Promise<void> { ... }
}
... and 100 other functions
组件规格:
describe('MyComponent ', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyComponent],
imports: [
...
],
providers: [
],
}).compileComponents().then(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
}));
// here I created a reference function for my base class spec
// Now, This is working but I don't want this **describe** and **it** to be here,
// it should be in the base file. so I can remove this repetitive code from all components.
// And From here I just want to call one function let's say a **baseGridSpecs(component)**,
// that will load all the specs of base class in this component.
describe('Should initialize Base grid', () => {
it('should have proper component.', () => {
const baseGridSpecs = new BaseGridSpecs<MyComponent>();
baseGridSpecs.runBaseGridTests(component);
baseGridSpecs.checkGetDataDefined(component);
});
});
});
基本规格:
export class BaseGridSpecs<T> {
runBaseGridTests(component: any): void {
expect(component).toBeTruthy();
}
checkGetDataDefined(component: any): void {
expect(component.getData).toBeDefined();
}
}
这个结构对我来说很好,但是它没有用,因为我的 describe
和 it
仍然在主要组件规范文件中。
What I am trying to achieve is to just call the base spec function like baseGridSpecs.runBaseGridTests(component);
and it should render all describe
and it
specs for given generic component.
任何帮助将不胜感激...
Jasmine 允许在 describe
块中定义 it
并且这些定义不会是 运行 除非您从某些 describe
块中显式调用它们。 Official documentation 提出了两种使用这一事实的方法。
测试主题可以与上下文共享,但它要求您使用 function
而不是箭头函数,并且可能很烦人且难以跟踪,尤其是当有许多嵌套块时,所以您的想法是class 规格是有道理的。
让我们考虑一个包含两个 classes 的简化示例。 (Playground)
// Base.ts
export class Base {
baseMethod() {
return 0;
}
}
和
// Derived.ts
import { Base } from "./base";
export class Derived extends Base {
derivedMethod() {
return 1;
}
}
派生 class 的测试,检查基础 class 部分可以封装在 BaseSpec
:
// base.spec.ts
export class BaseSpec {
public component;
checkComponentInitialized(): void {
it("should have proper component", () => {
expect(this.component).toBeTruthy();
});
}
checkBaseMethodDefined(): void {
it("should have baseMethod method", () => {
expect(this.component.baseMethod).toBeDefined();
});
}
itActsLikeABase(): void {
this.checkComponentInitialized();
this.checkBaseMethodDefined();
}
}
这个class然后可以在别处使用
// derived.spec.ts
import { Derived } from "./derived";
import { BaseSpec } from "./base.spec";
describe("Derived", () => {
describe("as a Base", () => {
const baseSpec = new BaseSpec();
beforeEach(() => {
baseSpec.component = new Derived();
});
baseSpec.itActsLikeABase();
});
describe("as a Derived", () => {
let component;
beforeEach(() => {
component = new Derived();
});
it("should have derivedMethod method", () => {
expect(component.derivedMethod).toBeDefined();
});
});
});
免责声明
虽然这在技术上是可行的,并且在某些情况下可能是合适的,但在以这种方式编写测试之前请三思。继承是一种强大但经常被误用的工具。由于测试共享行为而导致的重复很可能是意外重复,因为测试不应该依赖于行为的实现方式。 Sharing behavior testing caveats
因此,在 Shalang 的帮助下,我能够在我的基本网格规范文件中添加单元测试。
这是我所做的。
组件规格:
describe('MyComponent ', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyComponent],
imports: [
...
],
providers: [
],
}).compileComponents().then(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
}));
describe('Should initialize Base grid', () => {
const baseGridSpecs = new BaseGridSpecs<ComponentModel>();
beforeEach(() => {
baseGridSpecs.component = component;
baseGridSpecs.fixture = fixture;
});
// Here for me dummyData is model's object with proper value,
// which I can use to check service based calls.
baseGridSpecs.loadSpecs(dummyData);
});
});
基本规格:
export class BaseGridSpecs<T> {
public component;
public fixture;
loadSpecs(dummyData: any): void {
describe('Should initialize base component with Proper methods', () => {
it('should initialize properly.', () => {
expect(this.component).toBeTruthy();
});
it('should have Base getData function defined.', () => {
expect(this.component.getData).toBeDefined();
});
});
}
}
我有一个在每个网格组件中使用的通用基础 class。
现在,我有网格组件的规范,但我想在单独的基本规范文件中添加基本 class 的规范。
其背后的动机是删除重复代码并为基础网格制作通用规范文件,该文件将为每个使用基础的网格提供服务class。
我卡在了一点,我无法在基本规范文件中创建规范。基本上我希望基础文件中的所有规范都在一个函数下,当这个函数从子 class 调用该组件时,它应该 return 那个 class.[=50 的所有规范=]
Here is what I have and what I tried so far.
组件层:
export class MyComponent extends BaseGrid<MyEntity> {
... (and all other code like constructor and methods)...
}
基础层:
export class BaseGrid<T> {
public async getData(): Promise<void> { ... }
}
... and 100 other functions
组件规格:
describe('MyComponent ', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyComponent],
imports: [
...
],
providers: [
],
}).compileComponents().then(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
}));
// here I created a reference function for my base class spec
// Now, This is working but I don't want this **describe** and **it** to be here,
// it should be in the base file. so I can remove this repetitive code from all components.
// And From here I just want to call one function let's say a **baseGridSpecs(component)**,
// that will load all the specs of base class in this component.
describe('Should initialize Base grid', () => {
it('should have proper component.', () => {
const baseGridSpecs = new BaseGridSpecs<MyComponent>();
baseGridSpecs.runBaseGridTests(component);
baseGridSpecs.checkGetDataDefined(component);
});
});
});
基本规格:
export class BaseGridSpecs<T> {
runBaseGridTests(component: any): void {
expect(component).toBeTruthy();
}
checkGetDataDefined(component: any): void {
expect(component.getData).toBeDefined();
}
}
这个结构对我来说很好,但是它没有用,因为我的 describe
和 it
仍然在主要组件规范文件中。
What I am trying to achieve is to just call the base spec function like
baseGridSpecs.runBaseGridTests(component);
and it should render alldescribe
andit
specs for given generic component.
任何帮助将不胜感激...
Jasmine 允许在 describe
块中定义 it
并且这些定义不会是 运行 除非您从某些 describe
块中显式调用它们。 Official documentation 提出了两种使用这一事实的方法。
测试主题可以与上下文共享,但它要求您使用 function
而不是箭头函数,并且可能很烦人且难以跟踪,尤其是当有许多嵌套块时,所以您的想法是class 规格是有道理的。
让我们考虑一个包含两个 classes 的简化示例。 (Playground)
// Base.ts
export class Base {
baseMethod() {
return 0;
}
}
和
// Derived.ts
import { Base } from "./base";
export class Derived extends Base {
derivedMethod() {
return 1;
}
}
派生 class 的测试,检查基础 class 部分可以封装在 BaseSpec
:
// base.spec.ts
export class BaseSpec {
public component;
checkComponentInitialized(): void {
it("should have proper component", () => {
expect(this.component).toBeTruthy();
});
}
checkBaseMethodDefined(): void {
it("should have baseMethod method", () => {
expect(this.component.baseMethod).toBeDefined();
});
}
itActsLikeABase(): void {
this.checkComponentInitialized();
this.checkBaseMethodDefined();
}
}
这个class然后可以在别处使用
// derived.spec.ts
import { Derived } from "./derived";
import { BaseSpec } from "./base.spec";
describe("Derived", () => {
describe("as a Base", () => {
const baseSpec = new BaseSpec();
beforeEach(() => {
baseSpec.component = new Derived();
});
baseSpec.itActsLikeABase();
});
describe("as a Derived", () => {
let component;
beforeEach(() => {
component = new Derived();
});
it("should have derivedMethod method", () => {
expect(component.derivedMethod).toBeDefined();
});
});
});
免责声明
虽然这在技术上是可行的,并且在某些情况下可能是合适的,但在以这种方式编写测试之前请三思。继承是一种强大但经常被误用的工具。由于测试共享行为而导致的重复很可能是意外重复,因为测试不应该依赖于行为的实现方式。 Sharing behavior testing caveats
因此,在 Shalang 的帮助下,我能够在我的基本网格规范文件中添加单元测试。 这是我所做的。
组件规格:
describe('MyComponent ', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyComponent],
imports: [
...
],
providers: [
],
}).compileComponents().then(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
}));
describe('Should initialize Base grid', () => {
const baseGridSpecs = new BaseGridSpecs<ComponentModel>();
beforeEach(() => {
baseGridSpecs.component = component;
baseGridSpecs.fixture = fixture;
});
// Here for me dummyData is model's object with proper value,
// which I can use to check service based calls.
baseGridSpecs.loadSpecs(dummyData);
});
});
基本规格:
export class BaseGridSpecs<T> {
public component;
public fixture;
loadSpecs(dummyData: any): void {
describe('Should initialize base component with Proper methods', () => {
it('should initialize properly.', () => {
expect(this.component).toBeTruthy();
});
it('should have Base getData function defined.', () => {
expect(this.component.getData).toBeDefined();
});
});
}
}