1

I have the following method that is removing duplicates from an array based on a given property:

   removeDuplicates(myArr, prop) {
        return myArr.filter((object, pos, arr) => {
            return arr.map(obj => obj[prop]).indexOf(object[prop]) === pos;
        });
    }

Now I need to unit test this method, but I don't know how.

describe('remove duplicates', () => {
  it('should remove duplicated objects from an array based on a property', () => {
   //..
  }
});

How can I properly test methods like this?

Codehan25
  • 2,704
  • 10
  • 47
  • 94
  • One way of doing this is to declare an array with sample data and one which should be the expected result after the function processed it. Then you compare (deep equality, not object references) the expected result with the actual result from calling your `removeDuplicates` function. – Tsvetan Ganev Nov 15 '19 at 08:32
  • So I need to spyOn that method and compare the two arrays right? – Codehan25 Nov 15 '19 at 08:44

2 Answers2

1

You import your removeDuplicates function.

You can follow the AAA pattern (Arrange Act Assert).

describe('removeDuplicates', () => {
  const fixtureComponent = TestBed.createComponent(YourComponent);
  it('should remove objects with same given property', () => {
   // Arrange
   const persons = [
     { id: 1, name: 'John' },
     { id: 2, name: 'Paul' },
     { id: 3, name: 'Ron' },
     { id: 4, name: 'John' },
     { id: 5, name: 'Louis' },
   ];

    // Act
    const distinctPersons = fixtureComponent.removeDuplicates(persons, 'name');

   // Assert
   expect(distinctPersons).toEqual([
     { id: 1, name: 'John' },
     { id: 2, name: 'Paul' },
     { id: 3, name: 'Ron' },
     { id: 5, name: 'Louis' },
   ]);
 }
});
Florian
  • 1,473
  • 10
  • 15
  • maybe component.removeDuplicates(persons, 'name'); NO? – Fateh Mohamed Nov 15 '19 at 08:50
  • I don't think that `removeDuplicates` is a method inside a component. I guess OP created a _class helper_ that he uses inside components that need to remove duplicates from array. – Florian Nov 15 '19 at 08:52
  • If like what you said, then the unit testing should be placed in service. Might be `service.removeDuplicates` not call directly from unit test. – Jimmy Lin Nov 15 '19 at 08:54
  • Your approach is working fine, but I had to call the method like: component.removeDuplcates(persons, 'name'); Adjust your answer and I'll accept it :) – Codehan25 Nov 15 '19 at 09:01
  • @JimmyLin you do not necessarily have to create a service. Personnaly I would add my method on array such as : `Object.defineProperty(Array.prototype, 'removeDuplicates', removeDuplicates);`. Creating a service is overkill imho. – Florian Nov 15 '19 at 09:08
  • It's a better way to do it. @Codehan25. you should just extend the original array and not implement in the component. – Jimmy Lin Nov 15 '19 at 09:12
  • @JimmyLin I'm aware that _helper services_ (such as FormBuilder) are a thing, but here we are talking about processing arrays. In this case, a _helper service_ could be great if it creates custom arrays, but then you will end up with injecting the service in every components that requires arrays... – Florian Nov 15 '19 at 09:19
1

if it's a service try this

describe('removeDuplicates', () => {

  beforeEach(() => TestBed.configureTestingModule({
   providers: [
    YourServiceService 
   ]
  }));

  it('should remove objects with same given property', () => {

   const service: YourServiceService = TestBed.get(YourServiceService );

   const persons = [
    { id: 1, name: 'John' },
    { id: 2, name: 'Paul' },
    { id: 3, name: 'Ron' },
    { id: 4, name: 'John' },
    { id: 5, name: 'Louis' },
   ];

   let results = service.removeDuplicates(persons, 'name' );
   expect(results ).toBe([
    { id: 1, name: 'John' },
    { id: 2, name: 'Paul' },
    { id: 3, name: 'Ron' },
    { id: 5, name: 'Louis' },
   ]);
  })
})
Fateh Mohamed
  • 20,445
  • 5
  • 43
  • 52