title: ts-mockito - Stubbing method doesn't work when argument is a custom object
body: <p>In my rest architecture there is a controller (handle http request) and a service (business logic to provide data).</p>
  
  <p>To test the controller I'm trying to stub the service to provide a fixed response, but I didn't understand how stub a method which require a custom object as argument (if the argument is a literal it works).</p>
  
  <p>With a custom object (Farm) stubbing doesn't work because and I don't receive a Promise from service method, this is the error:</p>
  
  <blockquote>
    <p>TypeError: Cannot read property 'then' of null
    at FarmsController.createFarm (/Users/giovannimarino/Projects/rt-cloud/services/farms/src/farms/farms.controller.ts:17:17)</p>
  </blockquote>
  
  <p><strong>farms.controller.spec.ts</strong></p>
  
  <pre><code>describe('FarmsController', () =&gt; {
    const farmsServiceMock: FarmsService = mock(FarmsService);
    let controller: FarmsController;
  
    interface TestData {
      farm: Farm;
    }
    let testData: TestData;
  
    beforeEach(() =&gt; {
      reset(farmsServiceMock);
      const farmsServiceMockInstance: FarmsService = instance(farmsServiceMock);
      controller = new FarmsController(farmsServiceMockInstance);
  
      testData = {
        farm: &lt;Farm&gt; {
          name: 'CattD',
          imageUrl: 'img/farm-123b341.png',
          lang: 'en',
        }
      };
    });
  
    describe('createFarm function', () =&gt; {
      describe('success', () =&gt; {
        it('should return HTTP 200 OK', async () =&gt; {
          when(farmsServiceMock.createFarm(testData.farm)).thenReturn(Promise.resolve&lt;Farm&gt;(testData.farm));
          const pathParameters: PathParameter = {
            name: 'CattD',
          };
          const bodyRequest: Body = {
            name: testData.farm.name,
            imageUrl: testData.farm.imageUrl,
            lang: testData.farm.lang
          };
          const response: ApiResponseParsed&lt;Farm&gt; = await callSuccess&lt;Farm&gt;(controller.createFarm, pathParameters, bodyRequest);
          expect(response.statusCode).to.equal(HttpStatusCode.Ok);
        });
      });
    });
  });
  </code></pre>
  
  <p><strong>farm.controller.ts</strong></p>
  
  <pre><code>export class FarmsController {
    public constructor(private readonly _service: FarmsService) {
    }
  
    public createFarm: ApiHandler = (event: ApiEvent, context: ApiContext, callback: ApiCallback): void =&gt; {
      if (!event.body) {
        throw new Error('Empty input');
      }
      const input: Farm = &lt;Farm&gt; JSON.parse(event.body);
  
      this._service.createFarm(input)
        .then((data: Farm) =&gt; {
          return ResponseBuilder.created(data, callback);  // tslint:disable-line arrow-return-shorthand
        })
        .catch((error: ErrorResult) =&gt; {
          if (error instanceof NotFoundResult) {
            return ResponseBuilder.notFound(error.code, error.description, callback);
          }
  
          if (error instanceof ForbiddenResult) {
            return ResponseBuilder.forbidden(error.code, error.description, callback);
          }
  
          return ResponseBuilder.internalServerError(error, callback);
        });
    }
  }
  </code></pre>
  
  <p><strong>farm.service.ts</strong></p>
  
  <pre><code>export class FarmsService {
    public constructor(private readonly _repo: FarmsRepository) {
    }
  
    public async createFarm(farm: Farm): Promise&lt;Farm&gt; {
      try {
        return this._repo.create(farm);
      } catch (error) {
        throw error;
      }
    }
  }
  </code></pre>
  
  <p><strong>callSuccess</strong></p>
  
  <pre><code>export const callSuccess: SuccessCaller = &lt;T&gt;(handler: ApiHandler, 
  
  pathParameters?: PathParameter, body?: Body): Promise&lt;ApiResponseParsed&lt;T&gt;&gt; =&gt; {
    // tslint:disable-next-line typedef (Well-known constructor.)
    return new Promise((resolve, reject) =&gt; {
      const event: ApiEvent = &lt;ApiEvent&gt; {};
      if (pathParameters) {
        event.pathParameters = pathParameters;
      }
      if (body) {
        event.body = JSON.stringify(body);
      }
  
      handler(event, &lt;ApiContext&gt; {}, (error?: Error | null | string, result?: ApiResponse): void =&gt; {
        if (typeof result === 'undefined') {
          reject('No result was returned by the handler!');
          return;
        }
  
        const parsedResult: ApiResponseParsed&lt;T&gt; = result as ApiResponseParsed&lt;T&gt;;
        parsedResult.parsedBody = JSON.parse(result.body) as T;
        resolve(parsedResult);
      });
    });
  };
  </code></pre>