Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a code smell to have a special constructor only used during testing?

Assume I have a class Foo which is only instantiated with an instance of class Bar:

public Foo(Bar x) {
    this.a = x.a();
    this.b = x.b();
    ...
}

Now I would like to test Foo, further assuming an instance of Bar with the desired state is difficult to create. As an additional constraint, the fields a, b, ... are declared as final, so setters for this fields are not available.

A possibility would be to create an additional constructor in Foo:

protected Foo(A a, B b, ...) {
    this.a = a;
    this.b = a;
    ...
}

This constructor is only used during testing, which I would declare in the comment for this constructor.

Question: Is this a code smell?

Another solution I was thinking of was mocking Bar. Wonder if its the best practice in this case?

like image 445
mtsz Avatar asked Jun 05 '11 18:06

mtsz


2 Answers

Mocking Bar is more likely to be considered best practice. You should be able to create a MockBar so you can do

Foo foo = new Foo(new MockBar(a, b));
like image 161
Peter Lawrey Avatar answered Sep 18 '22 02:09

Peter Lawrey


I would probably consider that poor form, but if it works, it works. A preferable solution would be making a TestBar class that is a sub-class of Bar and overrides the methods in Bar. I guess that's pretty much mocking the object, as you alluded to in your question. It's a lot cleaner and allows you to define a different Bar implementation that can be included by your test driver.

like image 32
Mike M Avatar answered Sep 21 '22 02:09

Mike M