2

In my unit tests, I have to create stubs that have a large number of properties.

So I would have an interface like this:

interface Person {
  id: string;
  name: string;
  age: number
  ...
}

Then I will have to create an object that implements this interface and pass some values to each property. Doesn't Jasmine have a function that receives an interface and returns an object with default values?

In the example above, I would get:

const stub: Person = createStubObj<Person>();
stub.id // ""
stub.name // ""
stub.getAge // 0

I did some research but didn't found anything useful.

createSpyObj doesn't seem to help me because I don't have any functions that I want to spy on. The object only has properties.

This case can happen when an HTTP request returns a complex object (many properties, nested properties). I'm wondering how can I mock that object in that case, without needing to specify a value for each property.

Something similar to what this library is doing: https://www.npmjs.com/package/ts-auto-mock#usage

I'm wondering if this can be achieved in Jasmine as well or if there is a better approach

1 Answer 1

1

I tend to create specific mock objects that can be injected into the component under test using the TestBed provider registration:

    TestBed.configureTestingModule({
        providers: [
            TestComponent,
            { provide: RealInterfaceType, useValue: new MockObjectType() }
        ]
    });

You can then define the appropriate property values in the mock object. Equally you can use the mock object to be the response from a dependent service by setting up a spy:

    serviceSpy = jasmine.createSpyObj('SomeService', ['someFunction']);
    serviceSpy.someFunction.and.returnValue(new MockObjectType());

For http calls, I generally test them as follows...

let injector: TestBed;
let service: TestService;
let httpMock: HttpTestingController;
const expectedResponse: TestObject = new TestObject();

beforeEach(() => {
    TestBed.configureTestingModule({
        imports: [HttpClientTestingModule],
        providers: [
            TestService
    });
    injector = getTestBed();
    service = injector.get(TestService);
    httpMock = injector.get(HttpTestingController);
});

afterEach(() => {
    httpMock.verify();
});

describe('someFunction', () => {
    it('should return an Observable<UserAuthResponse>', () => {
        service.someFunction().subscribe(response => {
            expect(response).toBe(expectedResponse);
        });
        const req = httpMock.expectOne('http://the-expected-url');
        expect(req.request.method).toBe('GET');

        // return the static expected value
        req.flush(expectedResponse);
    });
});

This is merely testing the expecting http method and URL though.

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

3 Comments

Thank you for your response! What about the case where you need to mock the response from an HTTP service that is quite complex (has multiple properties, nested properties ...) ? Do you define each property with a default value? something similar like what this library is doing: npmjs.com/package/ts-auto-mock#usage but I'm wondering if this can be achieved in Jasmine as well or if there is another approach?
Updated my previous answer with the code I use for testing http services. Not sure if there is an easier way though.
That auto-mocking library looks useful - I will probably try that next time I write some angular code.

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.