-1

I'm new to unit testing and hope someone help me. I have a angular component called StudentComponent and it has following.

    public getAllStudents(){    
        this.apollo.query({
            query: GETALL_STUDENTS,
        }).subscribe((result: any) => {
            this.students = result?.data?.getAllStudents;
            this.students.forEach(element => {
            element.Age = this.CalculateAge(element.DateOfBirth);
            element.DateOfBirthString = this.getDateFormat(element.DateOfBirth);
            });
        });
    }

    public CalculateAge(dateOfBirth: any): number {
        let age = 0;
        if (dateOfBirth) {
            var timeDiff = Math.abs(Date.now() - new Date(dateOfBirth).getTime());
            age = Math.floor(timeDiff / (1000 * 3600 * 24) / 365.25);
        }
        return age;
    }

    getDateFormat(date: Date): string{
        let dateString = ""
        if(date){
            dateString = formatDate(date, 'yyyy/MM/dd','en_US').toString();
        }
        return dateString;
    }

I wrote the test case like following

    describe('getAllStudents', () => {
        it('makes expected calls', () => {
          spyOn(component, 'getDateFormat').and.callThrough();
          spyOn(component, 'CalculateAge').and.callThrough();
          spyOn(apollo, 'query').and.callThrough();
          component.getAllStudents();
          expect(apollo.query).toHaveBeenCalled();
          expect(component.getDateFormat).toHaveBeenCalled();
          expect(component.CalculateAge).toHaveBeenCalled();
  
        });
      });

this gave me an error. 'Expected spy getDateFormat to have been called.' Could anyone please guide me to resolve this?

1 Answer 1

0

The problem is that getAllStudents includes asynchronous code. With Observable.subscribe, your code will receive a delayed notification of the available result, most probably after expect has been evaluated.

There exist different ways to test asynchronous code with Jasmine (see Asynchronous Work from Jasmine documentation).

Angular also provides functionality to test asynchronous code. You can for example execute your unit test in the fakeAsync zone. Then, you need to invoke tick() just after calling getAllStudents(). This could look as follows:

it('makes expected calls', fakeAsync(() => {

  // given
  spyOn(component, 'getDateFormat').and.callThrough();
  spyOn(component, 'CalculateAge').and.callThrough();
  spyOn(apollo, 'query').and.callThrough();

  // when
  component.getAllStudents();
  tick();

  // then
  expect(apollo.query).toHaveBeenCalled();
  expect(component.getDateFormat).toHaveBeenCalled();
  expect(component.CalculateAge).toHaveBeenCalled();
}));

Please note that you're testing the implementation but not the result of the method. It would make more sense to consider the method getAllStudents() as a black box and check that Age and DateOfBirthString on all students are set as expected.

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

Your Answer

Draft saved
Draft discarded

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.