i have a question regarding testing classes like a converter.
Lets say i have a converter from EntityA to EntityB. The converter seems like this:
public EntityB convert(EntityA){
//call interal methods
return B.
}
private xy internalMethod1(...){
//call other interal Method
}
private xy internalMethod2(...){
....
}
private xy internalMethod3(...){
....
}
private xy internalMethod4(...){
....
}
The converter has one public method and 4 internal methods to convert the entity.
How should i test it?
Option1
I only test the public method and cover all cases from the internalMethods by different example inputs.
Advantages:
Testing only the "interface". Dont know the interal structure.
Internal refactoring is very easy and needs no changes at the tests.
Disadvantages:
Really big maybe unclear tests that tests all cases.
Every input must be pass all the methods.
Option2
I write tests for my public method and my private methods. (Some testframeworks can access private methods like powermock or spock (groovy))
I test every method alone and mock every other internal method.
Advantages:
Really small tests that only test the method itself and mock all other methods .
Disadvantages:
I know how it is implemented internal and must change the tests if i refactor some method, some methodname or something at the internal calling structure
Option3
I write some new classes that do the internal stuff and have public methods
Advantages:
Tests are maybe clearer and only for the special classes.
Disadvantages:
More classes for one conversion task.
Please help me what is the best practise here.
Maybe some good links/hints.
Thank you for your time.
The points you make are valid, but I think you might not be estimating their weight correctly.
Writing brittle tests (tests that are coupled to the implementation code) makes for a rigid code base that is hard to change. Since the point of writing tests in the first place is to be able to go fast, this is counter productive.
This is why you write your tests through the API only - it decouples the tests from the implementation. As you've said, this might make writing the tests a bit harder, but the reward is worth the effort since you'll get safety and be able to refactor easily.
Option 3 comes into play when you see a code smell where some tests cover only some of the code, and other tests only cover the other part of the code. This usually means there's a collaborator that maybe needs to be extracted. This is especially true when some internal functions only use some parameters and others don't. Also, when there's code duplication and the like.
What I would suggest, is to write it using the way you described in option 1, and then extract code out if needed, in the refactoring stage.
Related
I'm trying to write a unit test for an implementation of a Feign client. I wasn't sure how to go about it so I googled it and came across this answer and the accepted answer is this code snippet:
#Test
public someTestClient(){
Person expectedPerson = new Person("name",12));
when(mockPersonClient.getPerson()).return(expectedPerson);
Person person = mockPersionClient.getPerson();
assertEquals(expectedPerson, person);
}
I don't understand why this is a useful test or under what circumstance, other than a problem with the Person constructor, this test could ever fail. Isn't this test essentially the equivalent of:
Person person = new Person("a", 1)
Person expectedPerson = new Person("a", 1)
assertEquals(person, expectedPerson)
I understand unit testing should test functionality in isolation. Will this test just ensure that mockPersonClient exists at runtime?
We can configure a mock object to always return a hard coded and fake object when calling a method on that mock object.
In this example , the OP configured mockPersonClient.getPerson() return a fake Person.However, he just wonder why the fake person was not returned as configured when he called mockPersonClient.getPerson(). I think the codes example he shown was just for him to demonstrate this question. It does not mean he actually wrote that unit test codes to test some production codes.
A test like that doesn't have any value.
Here is a person, I am going to ask this call to return person and then I will check I got person when calling that thing. Of course you will get person, you just hard-coded that, so how is it useful?
Unit tests are about functionality, a simple fact which is lost on many.
Any code which changes data, which filters something, which changes something in a controlled way, is a good candidate for a unit test.
People use mocks a little bit too much and for most of the time for the wrong thing. Yes, we are advised to code against interfaces, but this doesn't mean you should have a very complex system, where you pass interfaces all over the place and then your test code tries to mimic that.
When you mock too much, it means the test you are writing is tied too much to the code it tests, it knows too much about it. Unit tests should not do that, because every time you change the code in some small way, you then discover that now you have to change the test, because you're no longer using 35 interfaces, now you have 47 to mock in a very specific order. That may not be an issue when you have one test, but imagine what happens when you have 1000 tests ...
If people tried to code in more of a functional way then this would not happen. If you pass data, instead of abstractions, now you don't have to mock anything.
Instead of mocking a call a database, isolate it, take the result and pass that to a method, you've just lost an abstraction and your code does not need to mock anything, you just call the method, pass the data in whatever format you want and see what happens.
If you want to test a real database, then you write an integration test. It's really not that complicated, mocking should not be the first thing you do, do it when it helps and you really must, but most of the time, you really don't and it simplifies things if you don't.
I am new to Unit Testing and recently tried my hands on JUnit test and Mockito.
I am trying to unit test a method that calls multiple private methods and also creates private objects of other classes.
How can I unit test the method.
For Example if I have the following code:
class ClassToTest {
private OuterClass outerClass;
public Boolean function() {
outerClass = new OuterClass(20);
return innerFunction(outerClass.getValue());
}
private Boolean innerFunction(int val) {
if (val % 2 == 0)
return true;
return false;
}
}
I'm confused how would I test the public function.
It doesn't matter how a method is implemented; that method should have a contract it obeys and that is what you are verifying with your test. In this example, function() should return true if the outerClass's value is even. One way to accomplish this would be to inject (pass into the ClassToTest constructor) the instance of outerClass so that you can control the value when testing:
#Test
public void trueWhenEven() {
var outer = new OuterClass(2);
var ctt = new ClassToTest(outer);
assertTrue(ctt.function());
}
Sometimes the contract is just that a method invokes methods on some other objects; in these kinds of cases, you can use Mockito or similar library to verify the interactions.
You are starting unit-testing with directly going at some non-trivial questions.
Question 1: How to handle implementation details / private functions? Answer: Unit-testing is about finding the bugs in your code, and that is one primary goal of unit-testing (and most other kinds of testing). Another primary goal is to prevent the introduction of bugs by acting as regression tests when the software is changed. Bugs are in the implementation - different implementations come with different bugs. Therefore, be sure to test the implementation details. One important tool to support here is coverage analysis, which shows you which parts of the implementation's code have been reached by your tests.
You may even test aspects beyond the contract of the function: a) Negative tests are tests that intentionally check behaviour for invalid / unspecified inputs, and are important to make a system secure. Because, even when provided with invalid input, the system should not allow to be hacked because of, for example, reading or writing out-of-bounds memory. This, however, does probably not apply for your example, because your method most likely is specified to implements a 'total function' rather than a 'partial function'. b) Tests of implementation details (if accessible) can even be performed beyond what is needed by the current implementation. This can be done to prevent bugs in upcoming changes to a component, like, extensions of the API.
There are, however, also secondary goals of unit-testing. One of them is to avoid that your tests break unnecessarily when implementation details change. One approach to also reach the secondary goal is, to test the implementation details via the public API. This way certain kinds of re-design of the implementation details will not break your tests: Renaming, splitting or merging of private functions would not affect the tests. Switching to a different algorithm, however, likely will require you to re-think your tests: Tests for an iterative / recursive implementation of the fibonacci function will look different than for an implementation using the closed-form-expression from Moivre/Binet, or for a lookup-table implementation.
For your example this means, you should try to test the functionality of your private function via the public API.
Question 2: How to deal with dependencies to other parts of the software? Unit-testing focuses on finding the bugs in small, isolated code pieces. When these code pieces have dependencies to other code parts, this can negatively influence your ability to unit-test them properly. But whether this is really the case depends on the actual dependency. For example, if your code uses the Math.sin() function, this is also a dependency to a different code part, but such a dependency does typically not harm your ability to properly test the code.
Dependencies to other components bother you in the following cases: The use of the other components makes it difficult to stimulate all interesting scenarios in your code under test. Or, the use of the other component leads to non-deterministic behaviour (time, randomness, ...). Or, the use of the other components causes unacceptably long build or execution times. Or, the other component is buggy or not even available yet.
If all of these criteria are not met (as it is normally the case with the Math.sin() function), you can typically just live with the other components being part of your tests. You should, however, keep in mind that in your unit-tests you still focus on the bugs in your code and do not start to write tests that actually test the other components: Keep in mind that the other components have tests of their own.
In your example you have chosen Outerclass to have some apparently trivial functionality. In this case you could live with Outerclass just remaining part of your tests. However, it is only an example from your side - The real other class may in fact be disturbing according to the above criteria. If that is the case, then you would somehow have to manage that dependency, which all requires in some way to come to a design that is testing-friendly.
There is a whole family of approaches here, so you better search the web for "design for testability" and "inversion of control". And, you also should try to learn about what distinguishes unit-testing and integration testing: This will help you to avoid trying to apply unit-testing on code parts that should rather be tested with integration testing.
Generally with Mockito this would require the use of Dependency Injection and then you would inject a mock of OuterClass for the test.
If you'd really like to test this without a Spring type framework being added I can think of 3 options:
1) Make this an Integration Test and test the real instances of everything
2) Alter your code so that OuterClass is created via a passed in Object from a setter or a constructor and then pass in a mock for your test
3) Change private OuterClass outerClass; to protected OuterClass outerClass; and make sure your test package structure is the same as your actual code package structure and then you can do outerClass = Mockito.mock(OuterClass); in your test set up.
I always have the doubt if unit testing isolation should be done at very fine grain like stubbing internal method calls, look at the following example with Java, JUnit and Mockito.
package com.company.domain;
public class Foo {
private FooHelper helper;
public setHelper(FooHelper helper) {
this.helper = helper;
}
public Double method1(Integer a, Integer b) {
... // logic here
Integer var = method2(a); // internal call to method2
... // more logic here
}
protected Integer method2(Integer c) {
... // logic here and return an Integer
}
}
This is the test class:
package com.company.domain;
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#Mock private FooHelper fooHelperMock; // mocking dependencies as usual
#InjectMocks #Spy Foo foo; // this way we can stub internal calls
#Test
public void method1Test() {
doReturn(2).when(foo).method2(1); //stub the internal method call
... // stub fooHelperMock method calls here
Double result = foo.method1(1, 2);
assertEquals(new Double(1.54), result);
verify(foo, times(1)).method2(1);
... // verify fooHelperMock method calls here
}
#Test
public void method2Test() {
... // stub fooHelper method calls here
assertEquals(new Integer(5), foo.method2(3));
... // verify fooHelperMock method calls here
}
}
I think this way you are able to really isolate the code under testing at method level even with internal calls. But I cannot find lot of information about this being considered a good practice or not and why.
In general, testing a class's internal function calls makes your tests far too fragile. When unit testing, you only want to see that the class as a whole is doing what it is supposed to do. You are supposed to intentionally ignore the internals.
Ignoring the internals has a lot of useful benefits. Mainly, if you change the methods -- as long as the public interface stays the same -- your tests will all still pass. Yay. This is the type of stability you want your unit tests to have. Fragile unit tests are almost worse than no unit tests. A fragile test has to be changed every time the code changes even if everything is still working. That provides you with nothing but extra work.
There are exceptions though. I would consider mocking out internal function calls in the following cases:
1) The internal call pulls data from somewhere. For example a database or large file. This is often called a 'boundary' test. We don't want to really set up a database or file to test, so instead we just sub out the function. However, if you find yourself doing this, it probably means that your class should be split into two classes because it is doing too many different things. Make yourself a dedicated database class instead.
2) The internal call does heavy processing that takes a lot of time. In that case, it might make sense to sub out the function instead of waiting. However, once again this might be a sign that you're on the wrong track. You should try to find a way to make things more partitioned so no single step takes that long.
In conclusion, I would highly recommend you do not test at the method level. A class should be a distinct unit. If the class is working everything is fine. This approach give you the testing you need to be secure and the flexibility you need to change things.
#raspacorp
Indeed, if you only test one case, someone could hardcode var = 2 and then pass your test case. But it is your job in designing tests cases to cover enough different cases to be reasonably satisfied that it is behaving appropriately.
As far as tests changing because the code has changed, this is not what you want at all. You want your tests to verify that the responses you are getting are correct for all the different types of cases. As long as the responses are correct, you want to be able to change everything without changing the tests at all.
Imagine a large system with thousands of tests verifing that everything is working right. Now imagine that you want to make a HUGE optimization change that will make things go faster, but change how everything is stored and calculated. What you want your tests to allow you to do is only change code (not tests) and have the tests continually confirm that everything is still working. This is what unit tests are for, not catching every possible line change, but rather to verify that all the calculations and behaviors are corrent.
This article from Martin Fowler answers your question.
You're a mockist, as I'm, but there are many people who don't like this approach and prefer the classicist approach (e.g. Kent Beck).
Roy Osherove says that the goal of a test, when it fails, is to identify the production code causing the problem, and having that in mind is obvious that the more fine grained the better.
For sure being a mockist may be overwhelming for beginners, but once you're used to the mechanisms of a Mocking library the benefits are uncountable while the effort is not much higher than the other approach.
I do not think it is necessary and I would even go further to say you should not do this. You are writing more test code to test less of you application code. In general it is considered good practice to only test public methods, because a unit test should only be concerned whether a method under test satisfies its contract (i.e. does what it is supposed to do) and not how the method is implemented. If you have a bug in your private method, how will you know?
I am trying to write a EasyMock Junit test case for some code which is having a lot of extra bits and pieces of code which I am finding a little overkill to Mock.
Say for the given example http://java.dzone.com/articles/easymock-tutorial-%E2%80%93-getting,
Following expectation is set to test
portfolio.getTotalValue()
Expectation
EasyMock.expect(marketMock.getPrice("EBAY")).andReturn(42.00);
EasyMock.replay(marketMock);
Now in my case there are around 30-40 such expectations that I need to set before I can come to my piece of code to unit test.
Is there a way to generate expectations of a code or dynamically generate them ? So that I don't have to manually do all this stuff to test my specific piece of code ?
No.
Seriously, what would you expect it to do?
You can save some labor over the long run by looking at patterns of expectations in multiple tests, and combining those into reusable methods or "#Before" methods.
Actually, it's a code smell: Hard-to-Test Code. Your object might not fulfill the Single Responsibility Principle (SRP).
You can try extracting out some expectations to one or more allowXY or createMockedXY helper methods (void allowDownloadDocument(path, name, etc), Document createMockedDocument(...) for example). Eliminating static helper classes also could be helpful.
I'm testing a function that takes several paramters and on the basis of their values calls different private methods.
I want to check that the function always call the right private method.
Since I know what the private methods will do I can check the final result but it would be more convenient to be able to check directly if the right function was called, because I have already tested the private methods.
Is there a way to replace a privae method with a stub?
Yes, there are mocking libraries that let you do this. One is PowerMock. From their private method tutorial, you need something like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyUnit.class)
public class TestMyUnit {
#Test
public void testSomething() {
MyUnit unit = PowerMock.createPartialMock(MyUnit.class, "methodNameToStub");
PowerMock.expectPrivate(unit, "methodNameToStub", param1).andReturn(retVal);
EasyMock.replay(unit);
unit.publicMethod(param1);
EasyMock.verify(unit);
}
}
However, I really disagree with this practice myself. Your unit test should test inputs, outputs, and side effects, and that's it. By ensuring that a private method is called correctly, all you're doing is preventing your code from being easily refactored.
In other words, what if down the road you want to change how your unit does its job? The safe way to do this is to make sure the code is under (passing) tests, then refactor the code (potentially including changing which internal methods are called), and then run the tests again to make sure you didn't break anything. With your approach, this is impossible because your tests test the exact implementation, not the behaviour of the unit itself. Refactoring will almost always break the test, so how much benefit is the test really giving you?
Most often you would want to do this because you're actually considering those privates a unit unto themselves (this sound like you, since you say you are testing those private methods directly already!). If that's the case, it's best to extract that logic into its own class, test it, and then in the remaining code interact with a mock/stub version of that new unit. If you do that, your code has a better structure and you don't need to fall back on the voodoo magic that is PowerMock. A fantastic reference to do these kinds of refactorings is Michael Feathers' Working Effectively with Legacy Code.
You may check java instrumentation to do so
As one of solution can be used proxy from inner classes. You need add inner class inside every your class which must be tested.
But it is not very good solution for big product project. its require create addition script for remove generated classes from your release files(jar/war).
But more easier way will be used PowerMock as wrote in comments bellow(or upper :)) - http://code.google.com/p/powermock/wiki/MockPrivate
Would it be possible to provide the class in question with another object, to which the private methods are moved and made public? In that case, it would be easy to create a test dummy for that interface.
If calling the right "private method" has no observable outside result, are you sure you want to test this? Maybe shouldn't.
If the end result is the same regardless of whether the private method gets called, and you still want to observe its invocation, you could make the method public and move it to its own class, and mock that class. Then you could verify (using Mockito or a similar framework) whether your method is being called.
Code coverage tools do this kind of thing by re-writing the bytecode before the tests are actually run. So, it's got to be possible, but it's non-trivial.
Update: writing a unit test that requires that the "right" private method be called kind of makes the job of refactoring a real pain because then you have to re-write all your tests. That kind of defeats the purpose of the tests.