Search code examples
androidunit-testingcode-coverage

100% unit test code coverage - how to achieve with 'defensive' coding?


How would you go about getting 100% code coverage with the code below?

- (void)methodA {
    mState = Active;
    // do something ...
    methodB();
}

- (void)methodB {
    if (mState != Active) return;
    // do something else ...
}

I can test the do something and do something else parts easily, the problem lies in the if (mState != Active) return; line of methodB. Since methodA is always setting the state to Active, the early return will never be executed.

I have the early return code in place just in case methodB is called elsewhere in the future. The code does not make sense to execute if mState is not Active, so it's defensive coding more or less.

I can add comments to the method stating "this method assumes the state is Active" or something, but that doesn't enforce the contract that the state must be active. Throwing an exception and/or asserting could be possibilities here too, but again I'm not sure how I could test that to get 100% code coverage.

I totally understand that for cases like this it is probably irrelevant to get 100% code coverage - but unfortuantely the decision to get is not mine (right now at least). The 'bosses' want this done, and are being unreasonable about this if you ask me!


Solution

  • First of all: don't get too hung up on 100% coverage. You can spend a lot of time to reach that number, without adding more "quality" to your product!

    Meaning: if that 100% goal is coming from an external driver, it might be worth to step back and discuss if a strict 100% goal really helps (I think it does not, but that is more of an opinion).

    Assuming you want those 100% coverage, I see only see one option: you enable your test to A) set mState to something else than Active and B) to be able to call methodB() without going through method methodA().

    For example by having a setter for that field; and making methodB() at least package protected so that a unit test can invoke the method. But then you are making "test only" changes to your production code - just for the purpose of hitting that magic 100% number.

    If mState is not a field, but would be returned by a getter, it might be possible to use a Mockito spy and partial mocking here.