1

I have a service which has two dependencies. One of them is a $http service responsible for making Ajax calls to my Rest API.

Inside my service I have this function:

this.getAvailableLoginOptions = function() {

    return $http.get(path.api + '/security/me/twoFA/options').then(function (resp) {
        return new TwoFaLoginOptions(resp.data);
    });

};

This function gets some options from my API and returns an object.

Now, how should I unit test this function properly? Normally I would just mock the $http service so that when the get function is called with a string parameter ending with '/security/me/twoFA/options' I would return a valid response with options.

But what if some other developer comes in and refactors this function so now it takes the options from another source e.i. another API or from browser's local storage but the function still works perfectly as it returns what it is supposed to do.

So what really unit testing is? Should we test every function as a black box and assume that if we give some input then we expect some particular output OR we should test it as a white box by looking at every line of code inside a function and mock everything but the test will be strongly dependent on all dependencies and the way how I use them.

Is it possible to write a unit test which tests if my function works properly no matter what algorithm or source of data is used to implement it? Or maybe this is actually a part of unit testing to check if my function really uses a dependency in this and that way (in addition to testing the function's logic)?

Łukasz Szkup
  • 117
  • 1
  • 9

1 Answers1

0

But what if some other developer comes in and refactors this function so now it takes the options from another source

This is exactly why Dependency Injection is used, because it makes it simple to manage dependencies between objects (easier to break coherent functionality off into separate contracts (interfaces), and thus solve the problem of swapping out object dependencies during runtime or compile time).

For example, you could have a ITwoFaLoginOptions with multiple implementations (service, local storage etc), and then you'll mock the interface get method.

Should we test every function as a black box [...] OR we should test it as a white box?

In general unit testing is considered white box testing (mocking the dependencies you have in order to obtain predefined responses that help you reach various code paths, while also asserting these dependencies have been called with the expected parameters), while system (or integration) tests would use a black box approach (for example calling the service like a client, assert against the response/DB).

Community
  • 1
  • 1
Alexandru Marculescu
  • 5,569
  • 6
  • 34
  • 50
  • Thank you for your answer Alexandru. I agree that instead of `new TwoFaLoginOptions(xxx)` I should use something like `twoFaLoginOptionsFactory.getNew(xxx)` so I can mock it easier. But if instead of `$http.get(path.api + '/security/me/twoFA/options')` I refactor it so it looks like this: `localStorage['twoFaOptions']`? In this case, I'm using completely different dependency to get data. So should I inject something else than `$http` or `localStorage`? I mean a service that wraps it and just serves data and only inside this service I should use `$http` or `localStorage`...? – Łukasz Szkup Jun 17 '16 at 10:56
  • that's **exactly** how you should go about this! – Alexandru Marculescu Jun 17 '16 at 10:56
  • Thank you for sharing your experience on this subject! – Łukasz Szkup Jun 17 '16 at 10:58