Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load multiple mocks for a single call #15

Open
jtasse opened this issue Aug 13, 2020 · 2 comments
Open

Load multiple mocks for a single call #15

jtasse opened this issue Aug 13, 2020 · 2 comments

Comments

@jtasse
Copy link

jtasse commented Aug 13, 2020

Background

I'll start by saying that this may be (hopefully) just my misunderstanding of how the mocks work.

In any case, I wrote a GAS method named getSummaryHTML() that calls getActiveSpreadsheet() (from SpreadsheetApp) and getSheetByName() (from the current spreadsheet), among other things.

Desired behavior:

I would like to be able to mock each of these calls and provide a return value for a single (test) call to the parent function.

Problem

TLDR; There does not appear to be a way to mock more than one dependency for a single function call/test.

As I understand it, the gas-local require method takes a single globalObject, which can be defined in a test like this:

var actualMock = {
            SpreadsheetApp: { getActiveSpreadsheet: function () { return 'TestSpreadSheetName'; } },
            __proto__: defMock
        },

This will successfully mock the behavior of getActiveSpreadSheet and return 'TestSpreadSheetName'.

However, if I wanted to mock the behavior for both getSummaryHTML() and getActiveSpreadsheet() within a single test for a single method, there doesn't appear to be a way to facilitate this. For example, this doesn't work, as the require function is not set up to handle an array:

var actualMocks = [
        {
            SpreadsheetApp: { getActiveSpreadsheet: function () { return 'TestSpreadSheetName'; } },
            __proto__: defMock
        },
        {
            SpreadsheetApp: { getSheetByName: function () { return 'TestSheetName'; } },
            __proto__: defMock
        }
    ];

Possible Solution

I did look into possible adding a multiplerequire function to bundle the mocks together in a single object, but I don't know enough about how Context objects work at the moment (e.g. - I could call require multiple times, but I believe that would just run the test once for each mock object, which is not what I want).

@andodet
Copy link

andodet commented Sep 7, 2020

I am facing the exact same problem: in my case a method relies on couple functions from UrlFetchApp but I have successfully managed to mock just one of the two.

/**
 * API call to fetch the time in Rome
 * @returns {string} A date string with format `%Y-%m-%d`
 * @customfunction
*/
function FETCHTIME() {
  const res = UrlFetchApp.fetch('http://worldtimeapi.org/api/timezone/Europe/Rome');
  let time = JSON.parse(res.getContentText());

  // Get date from timestamp
  time = time.datetime.slice(0, 10);
  return time;
}

And here's my test where I want to check the function actually returns the right date:

const { assert } = require('chai');
const gas = require('gas-local');

const defMock = gas.globalMockDefault;
const customMock = {
  UrlFetchApp: {
    fetch: function () { return 'HTTPResponse'; },
    getContentText: function () { return 'verylongstring'; },
    __proto__: defMock
  }
};

// Import function in custom module
var glib = gas.require('./src', customMock);

describe('fetch_time', function () {
  describe('#FETCHTIME', function () {
    it('should return a "%Y-%m-%d" string', function () {
      assert.equal(glib.FETCHTIME(), '2020-09-07')
    })
  })
})

The test fails with a TypeError: res.getContentText is not a function.

@andodet
Copy link

andodet commented Sep 7, 2020

Right, with a bit more research I've stumbled onto this repo which has a great example of how to use custom mocks.

The gist is to have a test/mocks folder and define mocks for single services in there, once you mocked everything you need you can import them in your test (example here.

edit: I agree with #12, being many ways to set things up I believe that a guide on how to move the first steps would be very helpful to get people productive faster. Could be easily written using Github wikis

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants