2

I was writing unit tests for a angular2/4 app. I wrote a function unit test which basically calls a function and expect the attributes the component object change.

Here are part of the code:

Component:

export class LoginComponent{

  constructor(private loginService: LoginService){}; 

  noUsername: boolean= false; 
  noPassword: boolean= false; 

  setStarFlag(id:boolean, pw:boolean){
      this.noUsername = id;
      this.noPassword = pw;
  }

}

Unit test:

var fixture: ComponentFixture<LoginComponent>,
    component: LoginComponent,
    loginService: LoginService, 
    loginServiceStub: LoginServiceStub;

describe('LoginComponent', () => {

beforeEach(async(() => {

    //set up testing environment
    TestBed.configureTestingModule({

        declarations: [LoginComponent],

        providers: [
                    { provide: HttpModule, useValue: true }, 
                    { provide: Http, useValue: true }, 
                    { provide: Router, useValue: true },
                   ] 

    }).overrideComponent(LoginComponent, {
        set: {
            //override original service with a stub one
            providers: [
                { provide: LoginService, useClass: LoginServiceStub},
                { provide: ActivatedRoute, useValue: { params: Observable.of({resumePath: 'testpath'})} }
            ]
        }
    }).compileComponents().then(() => {

        fixture = TestBed.createComponent(LoginComponent); //end testbed config & create fixture that provides access to component instance itself

        component = fixture.componentInstance; //getting component itself

        loginService = fixture.debugElement.injector.get(LoginService); 

    });

}));


describe('function setStarFlag', ()=>{

    it('set the flag to the right values', ()=>{

        spyOn(component, 'setStarFlag');

        component.setStarFlag(true, false);

        expect(component.noUsername).toBeTruthy(); //this doesnt work
        expect(component.noPassword).toBeFalsy();  //this doesnt work
    })
});

The problem is that if i directly call the function setStarFlag using component.setStarFlag(true, false), the function setStarFlag cannot change the property noUsername and noPassword of component itself.

But lets say if I trigger the function by simulating a button click, the property noUsername and noPassword will change.

HTML file:

<button (click)="setStarFlag(true, false)"></button>

Unit test:

let btn = fixture.debugElement.query(By.css('button'));
btn.triggerEventHandler('click', null);

expect(component.noUsername).toBeTruthy(); //this works 
expect(component.noPassword).toBeFalsy(); // this works

Can anyone explain to me why and how to solve this problem (I was thinking using isolated unit test, but i guess the config will be a lot of work since i have services)?

0

2 Answers 2

6

If you want the spied-upon function to be called normally, add .and.callThrough() to your spy statement.

You should call spyOn(component, 'setStarFlag').and.callThrough();

component.setStarFlag(true, false);

Sign up to request clarification or add additional context in comments.

Comments

0

I finally figured out where the problem is.

So if we spy on functions, jasmine spy will stub the spied functions for the sake of spying. The function will then lose its true functionality in that case. If we remove the spyOn function from my code, it will work perfectly!

To people that encountered the same issue:

Use two separate specs to test the functionality and function calling.

source: https://jasmine.github.io/2.0/introduction.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.