0

Doing some TTD and trying to throw a custom exception I made called FailedToConnectError, but I keep getting my NoAccountFoundError.

Here is my test:

Server.SERVER_URL = 'http://www.test.com.fail';

server.getAccounts(['999999999']).catch(e=>{
    expect(e).toBeInstanceOf(FailedToConnectError);
});

The main thing with the next function is we are grouping the account ids into groups of 100's then builds an array of promises to run. (API will only let you look up to 100 accounts at a time):

public getAccounts(accountIDs: string[]): Promise<Account[]>{   
    return new Promise<Account[]>((resolve, reject) => { 
        let groupedAccountIds:string[] = this.groupAccountIdsByMaxRquestLimit(accountIDs);
        let promises: Promise<Account[]>[] = this.buildPromisesForGroupingAccounts(groupedAccountIds:string);

        Promise.all(promises).then(accountProfilePromises => {
            let accounts:Account[] = [];

            for(let accountProfiles of accountProfilePromises){
                for(let accounts of accountProfiles){
                    accounts.push(accounts);
                }
            }

            if(accounts.length < 1){
                reject(new NoAccountFoundError());
            }

            resolve(accounts);
        }).catch(err => {
            reject(err);
        });

    });
}

Here is the buildPromisesForGroupingAccounts when also calls a function to send the http request.

private buildPromisesForGroupingAccounts(groupedIds:string[]){
    let promises: Promise<Account[]>[] = [];

    for(let accountIdsBy100s of groupedIds){
        let get100Accounts = new Promise<Account[]>((resolve, reject) => {
            var path = 'accounts/?'+'accounts='+accountIdsBy100s;
            this.websiteRequest(path, reject, (r:any,body:any)=>{
                  let accountsJSON = JSON.parse(body).response.players;

                  let accounts:Account[] = [];

                  for(let account of accountsJSON){
                      accounts.push(account);
                  }

                  resolve(accounts);
            });
        });

        promises.push(get100Accounts);
    }

    return promises;
}

Here is the website request function:

public websiteRequest(path:string, reject: Function, cb: Function){
    request.get({
        url:Server.SERVER_URL+path
      }, 
      async (err,r,body) => {
          if(err){
            reject(new FailedToConnectError());
          }else{
            cb(r,body);
          }
      });
}

Finally this is the error I get when I run my code:

(node:3835) UnhandledPromiseRejectionWarning: Error: expect(value).toBeInstanceOf(constructor)
Expected constructor: FailedToConnectError
Received constructor: NoAccountFoundError
Received value: [Error: No account found]
(node:3835) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:3835) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Tangela
  • 161
  • 2
  • 13
  • Please don't wrap `Promise.all()` in a manually created promise. That's a [promise anti-pattern](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it). Just use the promise that `Promise.all()` returns and return it. – jfriend00 Sep 04 '18 at 07:44
  • I don't see anything obviously wrong. Try adding some `console.log` statements or using a debugger to find out what is happening. I'd start by logging the URL and callback parameters in `websiteRequest`. – Matt McCutchen Sep 04 '18 at 16:36
  • @jfriend00 So I remove the manually created promise and just returned `Promise.all()`. Now my catch is working in my unit test. However is there a way I can get my `then()` logic to run before the return? Right now if I include the `then` logic and return it I get `UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)` – Tangela Sep 04 '18 at 21:18
  • No. Your function will return long before the `.then()` runs. That's how asynchronous operations work in Javascript. I don't see exactly what causes the unhandled promise rejection (or I would have written an answer explaining). Your `websiteRequest()` function is really not good and may be the cause (I can't tell). If you want to use promises here (which is a good idea), then get the `request-promise` library (a promise wrapper around the `request` library) and use it's returned promise rather than passing in a reject handler and/or using an async callback. That may fix the isssue. – jfriend00 Sep 04 '18 at 21:22

0 Answers0