Override method within JUnit test - java

I need to write coupling based test to observate several paths.
I am trying to do it like usual testing using Assert.* (I don't know any better way) but for that purpose I need to change the testing methods.
Consider following examples
Class A {
public Collection<Object[]> mth1(String a);
do whatever
do whatever
B.mth2(a)
do whatever
return null
Class B
public void mth2 (String a)
a.parse();
do whatever
return null
For my testing I'm not interested in actual values, I just need to know if my test comes to a certain point.
Thus, I want to override mth2 in such way - return is called at line 11
and mth1 to call return at line 6 with value 1.
Is there a way to do such thing or better way to test coupling?

Use a mock library (google search for mock). create a mock object for class B. use it in your test.

Related

Is it possible to mock System.identityHashCode?

Good day.
I have a tool which instruments objects in project by adding certain bytecode-generated toString implementation to each. The logic of generated toString is irrelevant but what important is that its return value depends on System.identityHashCode invocations, made inside.
Now I want to cover the generated logic with automated tests. I created a class for testing, generated toString for it and want to assert over its toString output. It's obvious that such test won't be reproducible, since System.identityHashCode gives different results between test runs.
Is it possible somehow to mock System.identityHashCode or stabilize the result it is given?
It is possible to do this using Powermock, as described here: How to Mock System.getProperty using Mockito
However, the better approach would be to create a class that wraps System and then inject the wrapper into the class you are trying to test.
Then in your unit test you can inject a test implementation of the wrapper and control the output from System.
I would introduce a testing seam:
#Override public String toString() {
return toString(System.identityHashCode(object));
}
/** Visible for testing. */
String toString(int hashCode) {
// Your implementation here.
}
This way, you can call toString(int) as many times as you want from adjacent tests without concerning yourself with PowerMock or even Mockito.
As an alternative, if System.identityHashCode is used elsewhere in your class such that results need to be consistent, you can take a replacement ToIntFunction in your constructor, and have the default implementation pass System.identityHashCode as a reference to a static method.
public YourWrapperClass(Object object) {
this(object, System::identityHashCode);
}
/** Visible for testing. */
YourWrapperClass(Object object, ToIntFunction<Object> hashCodeFunction) {
this.object = object;
this.hashCodeFunction = hashCodeFunction;
}

Correct design for certain methods

Consider you have a class RunMe. As the name supposes it is ran by another class. Let's asume through RunMe.run().
RunMe has a private variable with Data that it uses to run different Tests, lets call ist data.
Let's say this data is initialized by RunMe.initialize().
After that, in the run() Method, the first Test is ran with the default values set by the initialize function for data. Let's call that test-method testWithDefaultValues.
We now want to fill our data with some custom data. Let's say we do this using fillData.
Then we want to execute another test using our newly filled data. Let's call this test testWithFilledData.
Our run-method at this point would look something like this
public void run() {
initialize();
testWithDefaultValues();
fillData();
testWithFilledData();
}
Can you see how akward this code looks? It looks AND feels wrong. A thing directly coming into my mind: The only reason testWithFilledData() or also testWithDefaultValues()is actually doing what the name supposes is because of the order in which these functions are called in run. This has to be wrong.
So instead i should eliminate initialize and fillData and do what those functions do in the according test-function?
What if you consider the fact that many more test-functions are going to exist, each of them testing with a different set of data, all of which have to be quite manually filled (data.setField("fooField","fooValue);).
Can someone possibly give a general construct or idea in which he would explain how he would solve the given task properly?
Right now i am really struggeling to find a pattern that "feels nice" and correct. What i am doing currently must be wrong.
Edit: Worth mentioning is that the test-function cannot be generic. For every different variations of data different results have to be considered.
Well, what would happen if you attempt to call testWithDefaultValues() without calling initialize() first? You won't actually be testing with the default values, you will be testing with whatever you previously set data to. I think you should move away from modifying the internal test data in the actual test functions, and perhaps rather have a generic test function that has data passed into it.
This makes a lot of sense if testWithDefaultValues() and testWithFilledData() are actually doing the same thing but with different data.
I think something like this makes more sense:
Data testData = getTestData();
test(testData);
Data fillData = getFillData();
test(fillData);
I believe you should fill only one method with all the code needed for the test you are trying to achieve. You are then able to fill the variables or data for your test accordingly and stage different values for your data to run different test starting always from the same method.
With this simple construct, you are able to create multiple tests method and won't get lost in your code.
EDIT
You should always consider a test method like a blackbox testing. If you consider that you have no idea what's the code running inside the method. All you have to care about is the input and output of you test.
If the same method should produce different output based on different input. The code inside your blackbox remains the same.
However, if your method needs to interact differently with the input to generate the output you need, then, you need to consider writing a different test.
My two cents, hope it helps
I suggest using the Template Method design pattern to create a test framework. You'd probably be better off using a mature test framework like JUnit.
public abstract class TestCase {
// This is the template method.
public final boolean execute() {
initTest();
return runTest();
}
// Init hook method.
public abstract void initTest();
// Test logic hook method.
public abstract boolean runTest();
}
public abstract class BaseTest extends TestCase {
public boolean runTest() {
// This is the common execution for different data sets...
}
}
public Test1 extends BaseTest {
public void initTest() {
// Data init for test 1...
}
}
You can extend BaseTest for each test data set you have. To run the tests:
new Test1().execute();
new Test2().execute();
EDIT: You can of course skip BaseTest if you don't have common test logic. Or you can tailor the template method to add more hooks for whatever makes sense for your particular needs. The main point is to capture the common process in the template method, to isolate common code in some hook methods, and to provide unique concrete overrides in other hook methods.

Boolean method for testing [duplicate]

class Elephant extends Animal {
public Elephant(String name) {
super(name);
}
void makeNoise() {
logger.info(" Elephant make Sound");
}
void perform(String day) {
if (day.equals("thursday") || day.equals("friday")) {
makeNoise();
}
}
}
Now i want to test the perform method. How can I unit test this method using JUnit?
Solution with Mockito Spy
import org.junit.Test;
import static org.mockito.Mockito.*;
public class ElephantTest {
#Test
public void shouldMakeNoise() throws Exception {
//given
Elephant elephant = spy(new Elephant("foo"));
//when
elephant.perform("friday");
//then
verify(elephant).makeNoise();
}
}
Negative tests:
#Test
public void elephantShouldDontMakeNoisesOnMonday() {
//given
Elephant elephant = spy(new Elephant("foo"));
//when
elephant.perform("monday");
//then
verify(elephant, never()).makeNoise();
}
or
#Test
public void shouldDoNotMakeNoisesOnMonday() {
//given
Elephant elephant = spy(new Elephant("foo"));
//when
elephant.perform("monday");
then(elephant).should(never()).makeNoise();
}
Dependency
org.mockito:mockito-core:2.21.0
Read about
Mockito#doNothing()
Mockito#spy(T)
void() functions change the state of a program. This can be done by modifying a variable, a file, a database, etc.
In your case you're writing to a logger. If this results in writing " Elephant make Sound" to a file then you can read that file and see if the data in the file includes your noisy elephant.
If it however doesn't involve anything you can check (i.e.: it simply displays the output on the console) then you might want to look at some form of dependency injection (DI) where you can set the output to a file or something else you can easily read.
It should be noted that you can bypass DI by mocking the object and checking the appropriate methods are getting called.
To test any method, the responsibility to be tested must be visible from the out side of the method by changing state of any variable.
Typically it is done by returning value from the method. But without that, it can be done in many ways by modifying something from outside of the method scope, in case you have any "problem" to return something from the method!
In your case, you only log some message. And your code is not really testable in a sense that it does not do something that is directly related to changing the state of any variable (Because you change the state of other resource other than variable, that is not directly accessible by your code. You have to write some code to read the changes from that external resource, hence makes your testing code dependent to the reading also. If you have some problem with reading, your test case will not pass and that does not go with the spirit of the unit testing. The main idea is to reduce the dependency on external codes or libraries as much as possible). But your code can be testable by doing a slight refactoring / shifting responsiblity like below:
String makeNoise() {
return "Elephant make Sound";
}
String perform(String day) {
if (day.equals("thursday") || day.equals("friday")) {
return makeNoise();
}
}
And then you shift the responsibility of logging the value returned from perform method to the one using it like below:
logger.info(perform(day));
You have various options depending on the tools you are willing to use and the depth your tests should have.
Partial Mocking with plain Java
Create a class (MockElephant) that extends from elephant, overwrite makeNoise so it counts the number of invocations. Use that class in your test to check that makeNoise was called the correct number of times
Partial Mocking with a Framework
You basically do the same as above but instead of manually coding the MockElephant you create it using some mocking framework. Makes the test much simpler, since you need less code. And it is easier to read. But if strange things happen it makes it harder to understand what is going on. In case of Mocking frameworks I think they are worth it.
The reasons why this is called Partial Mocking is that you mock only parts of a class (a single method in this case).
The alternative is to use Normal Mocks, which in your case seems feasible (but can become tough in legacy code).
Here you would inject the Logger as a dependency. For example you could create an additional constructor which allows you to provide the Logger. In your test you would then use a mocked Logger, which again counts it's invocations, probably along with the parameter it received and check that it has the expected values.
Again you can do that with a Mocking Framework or with plain old Java.

How to unit test a private functionality

I have a question regarding unit testing.
I have a function which does the following thing:
void myFunction(List<MyClass> myList) {
// 1. Sort the list
// 2. Post Process the list
}
Now I want to test this function. But the problem is I should not test these two things at the same time. I am therefore thinking to extract the "Post Process the list" part as a separate function.
But the problem is the task of "Post Process the list" is only used by myFunction and I want to make it private to the class.
If I make it private I won't be able to test it from outside.
What is the general rule of this kind of scenario? Must I change a private function to public only for testing?
Or if there are any other patterns I should use?
Many thanks
The test method only needs to be package-local.
You can call private methods using reflections and there are mocking libraries which allow you to test private methods. But I would just make it package-local as it shows the method is access from elsewhere in the package (which it is either way)
As others have said, you don't need to make the method public, just package visible.
Google Guava has a #VisibleForTesting annotation which is meant for situations like this. You put this annotation on a method, just to document that the reason that the method isn't private is only for testing. The annotation doesn't do anything, it's just meant as a warning for programmers that they shouldn't call it from outside the class. (Some static code checking tool could in principle check if methods with this annotation aren't called from anywhere except inside the class or from test code).
Ofcourse it's kind of ugly to have to modify your code to do this just for testing. If you want to avoid this, you can do tricks with reflection to call the private method:
public class Sandbox {
public static void main(String[] args) throws Exception {
Example e = new Example();
Method m = Example.class.getDeclaredMethod("myFunction", List.class);
m.setAccessible(true);
m.invoke(e, Arrays.asList("one", "two", "three"));
}
}
class Example {
private void myFunction(List<String> data) {
System.out.println("Hey, what are you doing! " + data);
}
}
In general, you should always test the functionality through public methods. If there is some functionality in private methods, which cannot otherwise be tested well enough, that's an indication that the method has a responsibility which should be moved to its own class (this also helps to achieve high cohesion). Then that newly extracted class can be tested directly though its public methods.
Another vote for package-local. Just ensure that your newly exposed method is clearly named and documented so that in future it is not called inappropriately.
It depends.
Dose the sub routine contains common behavior that you should extract ?
Take your first sub routine as example. If you're not sorting your list by Comparator<T>, you should refactor it, then test that Comprartor<T> class instead of your private method. If Post process are actually some algorithm or common business logic, you might want to refactor it using Strategy pattern then test those class you just extract.
The point is, if a private method is complex enough to require a unit-test, then chance is probably you should not put them there, otherwise you should just test through it's public API.
It's a legacy system, and it will take forever to refactor that method.
check Bad Smells in Code : Long method for long method refactor, Method Object is a good strategy for things like this.
It's fine, I just want to test them.
Then you can test through Java reflection API, and I believe there are some mocking framework like PowerMock can also help you.
Below things you may consider for testing a private method.
1.create public method written only for the purpose of testing. (or)
2.create nested class for testing (or)
3.use reflection to test it.
useful link,another useful link from stackoverflow
I typically consider private methods to be part of the method under test. They typically consist of code that has been moved out of the original method to make it leaner and shorter, and more modular. However from a test perspective you would be testing the same code if you moved the content of the private method into your method under test.
The question of trying to isolate the return values of private methods to simulate various conditions is is often valid though. I think its' part of the larger question of how to write testable code.
One approach with very little overhead is to rely on basic overriding of methods. You can make your private methods protected virtual instead, and override them in your test:
Here's an example of that too :
http://www.unit-testing.net/CurrentArticle/How-To-Remove-Data-Dependencies-In-Unit-Tests.html
The example is C#, but the concept applies to all object oriented languages

unit test best practice for method with mocks in Mockito

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).

Categories

Resources