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
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).
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.
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).
Related
I am writing unit tests and meet a problem with builder:
Here is the class to be test:
public class ToBeTest() {
public void enact(SomeInput input){
Session s = Session.builder().attributeA(input.getA()).build();
s.attributeB("someValue");
}
}
How can I write a test to verify whether Session S set field A and also B successfully? Thanks!
Basically there are two things you can verify on:
input.getA(): mock that instance of SomeInput you provide to your code under test, then you can verify that mocked object later on!
Session.builder() is most likely a static call, so use static mocking to provide a mocked builder object, which you can verify later on, too. See the official documentation for the steps required to do that.
Having said that: your real problem is that you wrote "hard to test code". Surprise, that makes it hard to test. You see, what is the point of having a "method local" Sessions variable in the first place. If that method would return that s, you could then check if it has certain properties. Or if s would be a field of that class, you could then maybe do other checking, to ensure that a correctly configured Session was build.
Long story short: PowerMock(ito) offers the things you need to this code. Read some good tutorials and you shouldn't have much issues. But it would be worthwhile to also invest into improving your code under test to make it easier to test. My rule of thumb is: when you need PowerMock(ito) to test your code, then your production code should be improved.
I have encountered some java code where the public constructor calls a package-private constructor with a bunch of new operators to create new object.
public class Thing {
//public
public Thing(String param1, int paramm2) {
this(param1, param2, new Dependency1(), new Dependency2());
}
//package-private for the sake of testing
Thing(String param1, int param2, Dependency1 param3, Dependency2 param4) {
this.memberVar1 = param1;
this.memberVar2 = param2;
this.memberVar3 = param3;
this.memberVar4 = param4;
}
//...rest of class...
}
In my opinion, this is wrong because you are writing code to test it rather than writing correct code. I suppose the other two options (that I can think of) would be to create a factory or to use PowerMockito to inject a new object where applicable. Personally, I would have written as shown below.
public class Thing {
//public
public Thing(String param1, int paramm2) {
this.memberVar1 = param1;
this.memberVar2 = param2;
this.memberVar3 = new Dependency1();
this.memberVar4 = new Dependency2();
}
//...rest of class...
}
What is the best practice/correct way to implement this?
It is generally bad form to include test-specific code in anything that gets released (but there are exceptions, so don't read too closely). Here's a couple reasons why.
1. Someone external might use the test constructor in a way you never intended, hosing up everything, because they either didn't read the docs indicating it's meant for testing or the developer forgot to document it.
Let's say you wanted to write some useful extension of Thing but you couldn't find anything in Thing's public/protected API that did what you wanted it to. Then you find this package-private constructor that seems to allow what you were hoping for, only to find out later that it breaks your code. You still can't do what you wanted to and you wasted time exploring part of the API that didn't pan out. Anyone who does this will be left with a negative opinion of the API and won't be likely to recommend it to anyone else.
2. Refactoring the package name will break stuff.
This test code isn't very resilient to refactorings happening in the production code because of the way Java's default visibility works. The test code can only call that constructor if it resides in the same package. If the package gets renamed, the test code calling it won't be able to access it, causing compile errors. Sure, it's an easy fix for whoever is developing the code and the tests, but refactorings already aren't fun even without adding this minor annoyance. It becomes a major problem if a bunch of people were previously able to use the package-private stuff to suit their needs successfully - now all their code is broken too.
There are definitely cases where it's difficult write code that can be run in both the test and production environments (e.g. functions that only run when your application is networked). In those cases, dependency injection can be your friend, but simpler tests are always best if more complicated testing schemes can be avoided without sacrificing feature coverage or adding hooks into your API you never intended other developers to see.
I know there are good discussions of this exact topic elsewhere on StackExchange, but my luck with Google is not strong right now. The duplicates I've found are less than enlightening.
Is it a code smell to have a special constructor only used during testing?
https://softwareengineering.stackexchange.com/questions/239087/using-2-constructors-one-that-injects-dependencies-and-one-that-instantiates-th
Personally, I've seen three types of test code in production.
Branching logic - if (isTesting) foo() else bar();
Test method - Object foo(); is called by testing code but never in production.
Test constructor - Foo(Object dependency1, Object dependency2) is called by testing code but never in production.
The first two types are harmful in several ways.
Readability suffers because the code is longer and more complex. Business logic can be obscured by testing logic.
Maintainability suffers because the code has more responsibilities. Updating tests may require changes to production code.
In the best scenario, this test code is dead code in production. In the worst case, a client accidentally executes this test code in production causing unpredictable results.
The third type can of course be harmful in the same ways listed above; however, I believe a so-called test constructor can mitigate or eliminate the problems inherent to other types of test code in production.
Adding a constructor obviously lengthens the code (at least slightly) but it need not add complexity: if the constructors are chained, as in the example here, we have one which instantiates defaults and another which simply assigns fields. This separation can be less complex than a single constructor which does both. And if we follow the commonly accepted practice of not implementing business logic in our constructors, then we should have little risk of obscuring it.
Assuming, again, that our "test" constructor is chained to a production constructor and implements no logic other than assignment, the code actually hasn't added a responsibility to the class: it still instantiates and assigns dependencies, but as separate methods rather than one. There is no chance of a testing change breaking our production code.
Under the assumptions outlined, our test constructor is not dead code: it is actually called in production from whichever chained constructor the client invokes; therefore, a client executing this second constructor (with appropriate arguments) could expect the same contract as from the chained constructor.
Invoking new inside a constructor is generally bad for the same reasons that dependency injection is generally good. However, there are scenarios where sensible default implementations of a class's dependencies are obvious and instantiating those dependencies in a constructor provides the simplest possible interface to clients. In these scenarios, I find it appropriate to chain a second constructor which does not force any defaults, regardless of whether the second constructor facilitates testing.
As a bonus, the chained-constructor practice encourages programming to an interface because the second constructor makes you think about dependency implementations other than the defaults.
I am quite a beginner at unit testing and I got some failures that I do not know how to solve. I was trying to test my simple class Employee where I have static counter of created objects, so new employees can get consecutive numbers and default names like "Name1", "Name2" etc. Here is my default initiaiton block:
{
currentNr = ++count;
setName("Name"+currentNr);
setSurname("Surname"+currentNr);
}
I wrote one JUnit class with few methods. They are working fine but methods concerning counter are working only when I run them separately (they were also working when I saved them as separate tests, but it seemed messy having so many files).
When I run the class with all the testing methods, counter is adding more object and I do not know why/when/where as test are independent. In testing methods I am creating an object and checking the counter with assertEqual. Looking for solutions I tried to work with #Before, #After, etc. but it was the same or maybe I do not know how to use it properly.
My question is what could I do to have all the test methods working or what should I write in #Before method (I tried adding and deleting objects to ArrayList and/or setting to null). I guess it is not acceptable to have test working only when run separately.
Any help will be appreciated. Thanks!
Don't use static field as counter of employees. Use instance field instead:
public class Manager {
private int employeesCount;
public Employee addEmployee() {
employeesCount++;
Employee employee = new Employee();
employee.setName("John " + employeesCount);
employee.setLastName("Smith " + employeesCount);
return employee;
}
}
There are lots of good reasons not to use static fields (read: why static variables are bad) to maintain state and one of them is that this makes your code not-testable. If you maintain your state within object (in instance fields), then there is no problem to instantiate your object and just test it as is.
Instead, make sure that there is just one instance of Manager in your program and everyone works with it (this is called singleton). Well, there is singleton pattern. And many good reasons not to use it (read: why singletons are bad). So it ends up with the fact that when you write real app, you typically use some dependency injection framework (like spring or guice) and they have ability to instantiate singleton for you when you want it.
Well, it was a bit of humor here but I'm sure you get idea that global state is considered poor practice and difficulty to test it is one of ways how it manifests itself.
The answer frenzykryger is giving a lot of valuable insight, but there is a bit more to it.
You should always look at your work with SOLID in mind. In your example, the "Single responsibility principle" can guide to a better solution. You see, good OO programming is about creating helpful abstractions. And some of the abstractions that you put into Employee simply don't belong there.
For example, one can create a class Employee to model a human being working for some company. So, employees are human beings, so probably they have names; and as they are part of an organization, yes, they might have an ID.
But: an employee gets an ID assigned! When you start at a new company, people don't come up and ask you: "please tell us your new numeric ID". Instead, somebody comes to you and tells you "this is your numeric ID, don't forget it".
So, having that in mind, some advise:
An employee does not have setters for core attributes. So, properties like "ID" or "name" that are not meant to be changed should be passed as arguments to the constructor. You simply do not create an employee object and allow later on to change the name or the id of that entity!
So, as the other answer correctly pointed out: some external class, like a "Manager" has to keep track of all "known" employees; and if a new one is added, that Manager somehow computes a new, unique ID.
Finally: is is really true: static is an abnormality in good OO design. One should have really good reasons to turn to static fields (except maybe constants) and methods. static always leads to tightly coupled code - and that something to avoid!
Perhaps I have completely fallen short in my search, but I cannot locate any documentation or discussions related to how to write a unit test for a Java class/method that in turn calls other non-private methods. Seemingly, Mockito takes the position that there is perhaps something wrong with the design (not truly OO) if a spy has to be used in order to test a method where mocking internal method calls is necessary. I'm not certain this is always true. But using a spy seems to be the only way to accomplish this. For example, why could you not have a "wrapper" style method that in turn relies on other methods for primitive functionality but additionally provides functionality, error handling, logging, or different branches dependent on results of the other methods, etc.?
So my question is two-fold:
Is it poorly designed and implemented code to have a method that internally calls other methods?
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
This might be a difficult request, but I would prefer for those who decide to answer to not merely re-publish the Mockito verbiage and/or stance on spies as I already am aware of that approach and ideology. Also, I've used Powermockito as well. To me, the issue here is that Mockito developed this framework where additional workarounds had to be created to support this need. So I suppose the question I am wanting an answer to is if spies are "bad", and Powermockito were not available, how is one supposed to unit test a method that calls other non-private methods?
Is it poorly designed and implemented code to have a method that internally calls other methods?
Not really. But I'd say that, in this situation, the method that calls the others should be tested as if the others where not already tested separately.
That is, it protects you from situations where your public methods stops calling the other ones without you noticing it.
Yes, it makes for (sometimes) a lot of test code. I believe that this is the point: the pain in writing the tests is a good clue that you might want to consider extracting those sub-methods into a separate class.
If I can live with those tests, then I consider that the sub-methods are not to be extracted yet.
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
I'd do something like that:
public class Blah {
public int publicMethod() {
return innerMethod();
}
int innerMethod() {
return 0;
}
}
public class BlahTest {
#Test
public void blah() throws Exception {
Blah spy = spy(new Blah());
doReturn(1).when(spy).innerMethod();
assertThat(spy.publicMethod()).isEqualTo(1);
}
}
To me, this question relates strongly to the concept of cohesion.
My answer would be:
It is ok to have methods (public) that call other methods (private) in a class, in fact very often that is what I think of as good code. There is a caveat to this however in that your class should still be strongly cohesive. To me that means the 'state' of your class should be well defined, and the methods (think behaviours) of your class should be involved in changing your classes state in predictable ways.
Is this the case with what you are trying to test? If not, you may be looking at one class when you should be looking at two (or more).
What are the state variables of the class you're trying to test?
You might find that after considering the answers to these types of questions, your code becomes much easier to test in the way you think it should be.
If you really need (or want) to avoid calling the lower-level methods again, you can stub them out instead of mocking them. For example, if method A calls B and C, you can do this:
MyClass classUnderTest = new MyClass() {
#Override
public boolean B() {return true;}
#Override
public int C() {return 0;}
};
doOtherCommonSetUp(classUnderTest);
String result = classUnderTest.A("whatever");
assertEquals("whatIWant", result);
I've used this quite a quite a bit with legacy code where extensive refactoring could easily lead to the software version of shipwright's disease: Isolate something difficult to test into a small method, and then stub that out.
But if the methods being called are fairly innocuous and don't requiring mocking, I just let them be called again without worrying that I am covering every path within them.
The real question should be:
What do I really want to test?
And actually the answer should be:
The behaviour of my object in response to outside changes
That is, depending on the way one can interact with your object, you want to test every possible single scenario in a single test. This way, you can make sure that your class reacts according to your expectations depending on the scenario you're providing your test with.
Is it poorly designed and implemented code to have a method that internally calls other methods?
Not really, and really not! These so called private methods that are called from public members are namely helper methods. It is totally correct to have helper methods!
Helper methods are there to help break some more complex behaviours into smaller pieces of reusable code from within the class itself. Only it knows how it should behave and return the state accordingly through the public members of your class.
It is unrare to see a class with helper methods and normally they are necessary to adopt an internal behaviour for which the class shouldn't react from the outside world.
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
In my humble opinion, you don't test those methods. They get tested when the public members are tested through the state that you expect out of your object upon a public member call. For example, using the MVP pattern, if you want to test user authentication, you shall not test every private methods, since private methods might as well call other public methods from an object on which depend the object under test and so forth. Instead, testing your view:
#TestFixture
public class TestView {
#Test
public void test() {
// arrange
string expected = "Invalid login or password";
string login = "SomeLogin";
string password = "SomePassword";
// act
viewUnderTest.Connect(login, password);
string actual = viewUnderTest.getErrorMessage;
// assert
assertEqual(expected, actual);
}
}
This test method describes the expected behaviour of your view once the, let's say, connectButton is clicked. If the ErrorMessage property doesn't contain the expected value, this means that either your view or presenter doesn't behave as expected. You might check whether the presenter subscribed to your view's Connect event, or if your presenter sets the right error message, etc.
The fact is that you never need to test whatever is going on in your private methods, as you shall adjust and bring corrections on debug, which in turn causes you to test the behaviour of your internal methods simultaneously, but no special test method should be written expressly for those helper method.
Lets say we have method to test in class A that calls method from class B. To test it we created mock for B and then verify if it was called. Is verify(...) enough for unit test or I need assert actual result of tested method?
Below is simplified example to clarify my concern:
public class StringWriterATest {
StringWriterB b = mock(StringWriterB.class);
#Test
public void stringWriterATest() {
StringBuffer sb = new StringBuffer();
StringWriterA a = new StringWriterA();
a.stringWriterB=b;
a.append(sb);
ArgumentCaptor<StringBuffer> argument = ArgumentCaptor.forClass(StringBuffer.class);
verify(b).append(argument.capture());
assertEquals("StringWriterA", ((StringBuffer)argument.getValue()).toString());
//do we really need this or above is enough for proper unit test of method a.append(sb);
//assertEquals("StringWriterA_StringWriterB", sb);
}
}
public class StringWriterA {
public StringWriterB stringWriterB;
public void append(StringBuffer sb) {
sb.append("StringWriterA");
stringWriterB.append(sb);
}
}
class StringWriterB {
public void append(StringBuffer sb) {
sb.append("StringWriterB");
}
}
Regards,
Max
There is never a need to mock a return value and verify an object at the same time.
Consider this:
StringWriterA is the class under test. Therefore you'll definitely want to use assertions to verify the behavior of this class. In order to do this, you mock out a dependency, StringWriterB.
You do not want to test StringWriterB in your test of StringWriterA, therefore any assertions of StringWriterB interactions in your test are in the wrong place.
You must assume that StringWriterB is behaving as expected. You either want to verify that StringWriterA called StringWriterB correctly (using verify()) or you want to mock its expected behavior and mock the return values.
If you mock, then the verify is implicit since the mocked return value will not be returned if the method is not called.
In your case, StringWriterA.append() does not return any value, so only a verify is even possible. That StringWriterB.append() also works should have a similar verify test in a stringWriterBTest of its own.
Note: It's nice to be explicit with tests. Since test methods are never called outside of a framework, there is never a need to type them out, so you can have much longer method names than in production code methods. A nice convention is:
<underTest>Should<Expected>[When]<Condition>()
i.e.
stringWriterAShouldAppendConstantAndDelegateToStringWriterB()
stringWriterAShouldThrowNullPointerExceptionWhenNullArgument()
When you have test failures in your build (continuous integration), then you don't have to hunt down what went wrong, the method name appears right by the failure and you can read it to know exactly what behavior must be fixed.
In your example, StringWriterB stores no state and the append method could easily be static. In that case then the call is purely a side effect and does not need to be tested.
However, I suspect your real code is much more complex. If there is a of another object accessing StringWriterB then you maye want to mock it out in case there are unexpected calls to it. You also may want to add the verify of B if you expect it to be expanded in the future -- possibly storing state from the append call and having accessors.
One thing to consider is what the purpose of the call to StringWriterA.append() is. If it's job is to append the string StringWriterAStringWriterB then that is what you should be testing and a mock is not necessary. How StringWriterA accomplishes that task is immaterial. If, however, part of its job is to also call the StringWriterB.append() method then a mock may will be necessary unless you want to test StringWriterB in A's test.
My rule of thumb WRT mocks is to use real objects until the wiring for the objects I'm not directly testing gets too hairy or too brittle. If I feel like a good portion of my tests are in actuality testing other objects then mocks would be a good idea.
First of all try to show somebody the test you wrote. It is hard to read in my opinion. You can't really tell from it what behaviour you are testing. A brief intro for you how to make it a bit more readable can be found here How to Write Clean, Testable Code .
Using argument captors is also a smell. Some examples how to avoid it can be found on this tdd blog.
To answer you question, verify is used to verify interactions between classes. It is used to drive the design of your code. The result (if needed) should be specified by a when or given at the beginning of your test.
Further information how to drive your design with mocks (when, given, verify, ...) and how mocks are different to stubs can be found here: Mocks are not stubs. That example uses JMock not Mockito for defining mocks, but it is very similar (it is about the concepts, not the details of implementation and libraries you use).