Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it important to unit test a constructor?

Ought I to unit test constructors? Say I have a constructor like this:

IMapinfoWrapper wrapper;
public SystemInfo(IMapinfoWrapper mapinfoWrapper)
{
    this.wrapper = mapinfoWrapper;
}

Do I need to write a unit test for this construtor? I don't have any getters for the wrapper variable, so I don't need to test that.

like image 921
Nathan W Avatar asked Dec 10 '08 23:12

Nathan W


People also ask

Is unit testing really necessary?

Unit testing ensures that all code meets quality standards before it's deployed. This ensures a reliable engineering environment where quality is paramount. Over the course of the product development life cycle, unit testing saves time and money, and helps developers write better code, more efficiently.

Do you need to test constructor in Java?

Since the fields of a class are (usually) private, in order to test that a field has the correct value, you have to call a getter method to get the value of the field. Thus, testing that a constructor does its job automatically tests the getter methods; you don't need more tests for the getter methods.

How do you call a unit test constructor?

The simple way to test anything inside constructor function is to create component instance and then test it. it('should call initializer function in constructor', () => { TestBed. createComponent(HomeComponent); // this is the trigger of constructor method expect(sideNavService.

Why is unit testing not important?

The problem with unit testing is that it requires a behavioral change, and it is very hard to change people's behavior. With words, you will get a lot of people to agree with you, but you won't see many changes in the way they do things. You have to convince people by doing.


10 Answers

Unit testing is about testing the public states, behaviors, and interactions of your objects.

If you simply set a private field in your constructor, what is there to test?

Don't bother unit-testing your simple accessors and mutators. That's just silly, and it doesn't help anyone.

like image 104
yfeldblum Avatar answered Sep 27 '22 15:09

yfeldblum


Yes. If you have logic in your constructor, you should test it. Simply setting properties is not logic IMO. Conditionals, control flow, etc IS logic.

Edit: You should probably test for when IMapinfoWrapper is null, if that dependency is required. If so, then that is logic and you should have a test that catches your ArgumentNullException or whatever... your tests are specifications that define how the code behaves. If it throws an ArgumentNullException, then that should be specified in a test.

like image 30
Brian Genisio Avatar answered Sep 27 '22 15:09

Brian Genisio


Q: If you are setting a member variable in the constructor, why are you setting it.

A: Because you have a failing unit test that can only be made to pass by setting it in the constructor.

If you use this logic, where you only write code to cause a unit test to pass (Test Driven Development), then you will already have the answer to your question.

like image 20
John Sonmez Avatar answered Sep 29 '22 15:09

John Sonmez


No. Its functionality will be tested by every other unit test on the class.

like image 43
Draemon Avatar answered Sep 29 '22 15:09

Draemon


You absolutely should test the constructor. If you have a default constructor, you should test that it can be called. What if later on the class is changed--perhaps it becomes a singleton or the default constructor is removed in favor of one requiring parameters? The test should fail in that case to alert that change (so that the class or the test can be fixed to meet the new requirement).

The presence of a default constructor is a requirement that should have a test. Even if all the constructor does is set private members that will be tested elsewhere, the fact that there is a parameterless constructor should be tested.

like image 21
c g Avatar answered Sep 26 '22 15:09

c g


It depends.

I wouldn't bother writing a dedicated constructor test for something so simple as the example you gave.

However, if you have logical tests in the constructor such as a parameter validation, then yes, absolutely. Although, like the original poster, I do no work in the constructor if possible, it's common that parameter validation must be done. In this case it is unavoidable to keep the constructor from doing some work. If there's logic in the constructor, there's always the chance that it could be wrong, hence I treat it just like any other method call and test it appropriately.

like image 36
Mark Simpson Avatar answered Sep 27 '22 15:09

Mark Simpson


I am testing constructors when they contain logic - e.g. validation or conditional setting a private state. Validation errors end up in an exception thrown from the constructor. Successful execution ends up in a creation of object which exhibits specific behavior depending on the state which was set in the constructor. In either way, it requires testing. But constructor tests are boring because they all look the same - invoke the constructor, make an assertion. Test method declarations often take more space than the whole testing logic... So I wrote a simple testing library which helps write declarative tests for the constructors: How to Easily Test Validation Logic in Constructors in C#

Here is an example in which I am trying seven test cases on a constructor of one class:

[TestMethod]
public void Constructor_FullTest()
{

    IDrawingContext context = new Mock<IDrawingContext>().Object; 

    ConstructorTests<Frame>
        .For(typeof(int), typeof(int), typeof(IDrawingContext))
        .Fail(new object[] { -3, 5, context }, typeof(ArgumentException), "Negative  length")
        .Fail(new object[] { 0, 5, context }, typeof(ArgumentException), "Zero length")
        .Fail(new object[] { 5, -3, context }, typeof(ArgumentException), "Negative width")
        .Fail(new object[] { 5, 0, context }, typeof(ArgumentException), "Zero width")
        .Fail(new object[] { 5, 5, null }, typeof(ArgumentNullException), "Null drawing context")
        .Succeed(new object[] { 1, 1, context }, "Small positive length and width")
        .Succeed(new object[] { 3, 4, context }, "Larger positive length and width")
        .Assert();

}

In this way, I can test all the relevant cases for my constructor without typing much.

like image 31
Zoran Horvat Avatar answered Sep 29 '22 15:09

Zoran Horvat


Testing accessors and mutators is also necessary unless the developer has ensured that no state logic can be changed. For instance, if one uses the design pattern for a Singleton, often times accessors or properties are used, and if the class is not initialized, it is done from the accessor since the constructor is private. In C++, one can make their functions const or static in which data members of the class cannot be changed. (Note: Even using static is a bit risky since those variables are often global.) However, without a test, if someone fails to use preventative measures, how can you guarantee with a 100% accuracy that what is written cannot become a failure over time? Maintenance is hardly foolproof.

like image 29
Brandon Avatar answered Sep 26 '22 15:09

Brandon


I think the answer to this is "Yes".

There's plenty of code out there which assumes, horribly, an initialised object state, instead of a null reference - often when there are no explicit values assigned in the constructor.

I am happy to have constructor tests break to alert me when initialised public member values have been changed. This is about defensive testing - I'm pragmatic, and happier to have tests than not, and remove them when they're shown to not be helpful or useful.

like image 22
badcop666 Avatar answered Sep 30 '22 15:09

badcop666


I believe in 100% coverage. Also 100% coverage not by simply testing simple interactions by mocking things or just setting and getting things, but more integration/acceptance tests that check functionality. So if you end up writing really good integration/acceptance tests, all of your constructors (and simple methods such as setters and getters) should be called.

like image 32
digiarnie Avatar answered Sep 28 '22 15:09

digiarnie