Douglas Toledo
Douglas Toledo

Reputation: 33

How to test the value of a variable that exists only inside that function?

I'm trying to implement some unit tests for a function, but one of the inputs does not change what the function returns. Even though this input won't change what the function returns, I still need it for an API inside the code. The function is something like this:

    public bool IsEmailSent(string userEmail, bool isJson)

    {

        var link = isJson ? "Link1" : "Link2";

        if (string.IsNullOrEmpty(userEmail))
        {
            return false;
        }

        //Some other code

        return true;
    }

What I'm trying to do is to test the variable 'link' value, which depends on the input 'isJson'. So the test I wanted to implement is something like:

     [TestMethod]
     public void link_should_be_link2_when_isJson_is_false()
     {
            //if isJson is false && link = link2, test is sucessful
     }

The problem is that I have no idea how to get the variable 'link' inside a test, to check if it's value is correct, since my function doesn't return it. So, how do I test a value of some function's variable that dependes on a given input, but my function doesn't return anything close to this variable's value?

Upvotes: 0

Views: 1851

Answers (2)

Dirk Herrmann
Dirk Herrmann

Reputation: 5939

Since the computation of link in your function does not have an impact on the return value, it will have some other observable effect, because otherwise the computation would not be needed. In your case it seems likely that the effect would be observable in the way your function link accesses a dependend-on-component (DOC), probably some function that sends out an email.

You have a multitude of options here:

  • You can mock the call to the DOC function that sends out the email to see if it is called as expected for your expected intermediate value of link.
  • You can factor out some helper functions from link as was suggested by elgonzo.
  • You could consider refactoring your code to avoid the Boolean control argument, which looks like a code smell, for example to have different functions for the Json and the non-Json case. However, the testing problem will then have to be solved according to the new design you chose.
  • ...

Some remarks, however: Unit-testing is not a black box technique. In fact, some of the unit-testing specific test design techniques only make sense for glass box (aka white box) testing, namely all the coverage based test design methods. An attempt to keep the whole unit-test suite independent of implementation details is likely to result in an inefficient test suite, that is, a test suite that is not suited to find all bugs that could be found.

Bugs are, in the end, in the implementation. Different implementations will have different bugs. Think about the different ways to implement a Fibonacci function: as iterative/recursive function, closed form expression (Moivre/Binet), lookup table: Every implementation brings different potential bugs. Unit-testing is the testing method at the bottom of the test pyramid, and all higher-level tests (integration or system test) are less suited to find bugs in the implementation details. And, finding bugs is one primary goal of testing (see Myers, Badgett, Sandler: The Art of Software Testing, or, Beizer: Software Testing Techniques, and many others).

The best approach therefore is to have as many as possible useful tests that are implementation independent. Additionally, you will likely need additional tests that aim at finding the potential bugs in the chosen implementation. However, the less stable an implementation aspect is, the more you should avoid making your tests dependent on it: Helper functions may be more likely to be renamed, merged or deleted than the functions forming the official API of your component.

Upvotes: 0

Paul Blackburn
Paul Blackburn

Reputation: 60

When performing unit testing, consider a function like a black box. Test combinations of inputs, test idempotence, etc. The implementation of the actually function can be abstracted away from the unit tests. Without seeing the

//Some other code

I would see if you can turn the API call into a helper function. Then, write separate unit tests for the helper function.

Upvotes: 1

Related Questions