开发者

Is it ok to unit-test an abstract class by instantiating it as a mock object?

It has come to my attention that you can unit-test an abstract class by instantiating it as a mock object. Thereby you mock the abstract properties and methods, while being able to test the implemented ones.

However, I am accustomed to distinguish between the class to test and the injected dependencies to mock/stub. So, in this early stage开发者_运维技巧 of my new enlightenment I wonder if there are any pitfalls to this way of testing?? Any thoughts on this?

Regards, Morten


An abstract class, to be of any value, should have concrete subclasses which can be instantiated. So unit test those, and via them implicitly the base class.

If it has no concrete subclasses, I can't think of any reason why it should exist (as an abstract class, that is).

In general, I prefer to use mocking only to set up the environment of the class to be tested, not to instantiate the class itself. This distinction - to me - keeps the test cases clearer, and ensures that I always test the real functionality of the class.

Of course, I can think of cases (with legacy code) when the main issue is to be able to write unit tests somehow, anyhow, to enable refactoring (as discussed in Working Effectively with Legacy Code). As a temporary solution in such cases, (almost) anything goes. But once the unit tests are working, the class should be refactored properly asap to make it clean and testable (and its unit tests too, to make them maintainable).


Instead of using inheritance to combine two classes, see if you can use composition.

So instead of this:

abstract class PaySalary {
    payAmount(decimal money) {
        if (transferAmount(money)) {
            isPaid = true;
        }
    }

    abstract void transferAmount(decimal money);
}

Do this:

class PaySalary {
    public MoneyTransferrer;

    payAmount(decimal money) {
        if (MoneyTransferrer.transferAmount(money)) {
            isPaid = true;
        }
    }
}

This way, you don't have to inherit the class in your unit test, but you can simply mock a MoneyTransferrer. You can also test the MoneyTransferrer without depending on the base class.


If there isn't a concrete implementation in the part I'm testing, I usually write a test-implementation. In the unit test I do something similar as the user of my classes does. If he inherits my class, I inherit in the test.

On the other side, I wouldn't say that it is bad to use a mock framework to create an implementation. In my cases I usually doesn't work, usually because I need to write ORM mapping files for that class and thing like this.


Yes, you will test an abstract class much like you test an interface with injection.

If you write a test for ILog and inject it for testing using MockLog then you would do the same for LogBase (which is an abstract class in this example) and inject it with MockLog just the same.

An abstract class is NOT an interface BUT they are used much the same from overhead.


An abstract class is by definition, abstract. There shouldn't be anything to test if it's truly abstract.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜