2

I am writing a unit test using mocks and would like to ask an opinion. My specific example is mocking the "window" object, however the problem could occur in other scenarios.

To note, I am reverse engineering the unit tests, TDD is a new style which we are adopting here.

The module I am testing is one that will return the hash part of the URL and grab parameters from it. For example if the hash value was:

#param=value&param2=value2

Then the module would return an object like:

{
  param: 'value',
  param2: 'value2'
}

The first unit test I am writing is one which returns the hash value without the hash. Here is the method:

getCurrentHash: function() {
    return window.location.hash.slice(1);
},

I have mocked the window object to set window.location.hash equal to #param=value&param2=value2

I am expecting getCurrentHash to return param=value&param2=value2 in this particular instance.

The window object is a dependency on the hash module, I have switched the path when running the tests to use the mocked version.

The Question

Should unit test explicitly test against the mocked data like this:

tdd.test('getCurrentHash', function () {
    var currentHash = hash.getCurrentHash();            
    currentHash.should.equal('param=value&param2=value2');
});

Or should the unit test be testing the format of the return value, like this:

tdd.test('getCurrentHash', function () {
    var currentHash = hash.getCurrentHash();            
    currentHash.should.not.contain('#');
    currentHash.should.be.a('string');
    currentHash.should.have.length.above(0);
});

This question came about due to the fact that the mock might change. If for example we decided to add spaces into our mock we would end up amending it to param=value&param2=value2+withspace. This would then make the test fail and I would need to change the test to:

tdd.test('getCurrentHash', function () {
    var currentHash = hash.getCurrentHash();            
    currentHash.should.equal('param=value&param2=value2+withspace');
});

However, in the case of the second test which is more generic, I would not need to change the unit test.

I have read a few articles including the ones listed below, but I couldn't find any detailed reasoning on what an assertion should assert

1 Answer 1

1

you want to test the behaviour you want to see from the thing you are testing. Your behaviour is (based on the implementation) that the window locations hash value minus the '#' char is returned. So you should test things like:

  • when no has values exist, nothing is returned (but no error is returned (unless you explicitly want that))
  • The expected value is returned when a value exists

your second test has little value IMHO as I could change the implementation to this and the tests would still pass.

getCurrentHash: function() {
    return "bob";
}

This makes the test fairly useless. your tests exist to verify the behaviour of the system. So write tests that set up happy path conditions, failure cases and edge cases and have them verify that things behave in the way you expect.

Sign up to request clarification or add additional context in comments.

1 Comment

This has been useful to encourage more conversation at work. Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.