ihebiheb
ihebiheb

Reputation: 5183

Unit testing a method that update only some properties

I want to unit test a method that set the property active of the class Person to True.

The class Person have many other properties :

public class Person{
    private int id;
    private Boolean active;
    private Boolean adult;
    ... more properties

    ... getters and setters
}

The method to test will look something like :

public void updatePersonStatus(int personId){
    Person person = getPersonById(personId);
    person.setActive(true);

    repository.save(person);
}

Is it sufficent to test only that the method save is called with an object person that have the property active true (Example using mockito):

    @Test
    public void activateTest() {
        ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
        Person testPerson = new Person();
        testPerson.setActif(true);

        responsableExamenService.updatePersonStatus(1);

        verify(theClass, times(1)).save(argument.capture()); //verify that the method save is called one time with a class Person as a parameter
        assertTrue(argument.getValue().getActive()); //and that the Object person have a property active to true.
    }

Or do I also need to test that every other property of Person have not bean altered ?

So in other words, does a unit test need to validate "what a method should do", or does does it need to validate only what a method should do without verifying possible side effects ? Here an example of side effect would be besides of setting active to true, a developper can also set the property adult to true.

PS : The example is in Java, but the question is valid for nearly every programming language

Upvotes: 2

Views: 1408

Answers (3)

Dirk Herrmann
Dirk Herrmann

Reputation: 5939

Unfortunately, the set of things a function shall not do is infinite. Not setting other than the desired attributes is only one possibility. And, when it comes to specifications, they are mostly only explicit with respect to what the function shall do. There is always an implicit "and nothing else", and only rarely some selected behaviours are explicitly excluded.

On the other hand, when you apply unit-testing to check that the code you have written behaves as you intend it to behave, then the problem gets manageable: There is a set of 'likely' bugs, and your tests should be designed to catch those. For example, you know if your code does I/O or not, and if not, there is no value in writing unit-tests to verify it does not do I/O. On the other hand, if you have good reason believe that it is a likely bug that the code does more than intended of a specific operation, then it is worth a test to ensure it does not.

The same applies, mostly, to code written by some other person, for example if you take over the maintenance of some code. In any case, unit-testing is a white-box testing technique, and the assumption is that you have access to the code, typically even the possibility to change it (to improve testability, for example).

Upvotes: 3

nyarian
nyarian

Reputation: 4365

The rule that I personally follow is to test what the method is supposed to do at first. I'll test something like "side-effect free" when and only when it either makes sense from the method implementation standpoint to apply such an effect (but it shouldn't) or (sticking to one of the TDD rules) when I am proving that the code works (addressing your example - I wouldn't verify the absence of such a side effect at first, but if some developer had set an another property to true - I'll prove the mistake by writing a unit-test that verifies this side effect, and then I'll apply the fix).

Upvotes: 1

Igor Piddubnyi
Igor Piddubnyi

Reputation: 144

Simple answer - there is no strict rule. Unit testing stands for testing one "unit" of functionality.

In your case functionality is "updating person status". It should be defined by specification - what is expected in this case. And, in perfect world, your tests should verify only things specified.

Also it's a good idea to unit test one action at a time. E.g. first test could verify base functionality, while second check for a side effects.

Upvotes: 1

Related Questions