Mockito JUnit testing: check method call in constructor - java

I have a class Foo with private and public or protected methods. For example:
public class Foo{
private int number;
public Foo(){
setup();
doSthing();
}
private void doSthing(){
number=10;
}
public void setup(){
}
protected int getNumber(){
return number;
}
public void run(){
getNumber();
//Do blah blah...
}
}
And I am trying to test this class using Mockito.
public class FooTest
{
public void testMethods()
{
Foo foo = PowerMockito.mock (Foo.class);
//1 What should I do to see that setup() and doSthing()
//has been called on Foo construction
mock.run();
//2 What should I do to see that getNumber()
//has been called on run() method call
}
}
I am also hoping to include "times(1)" if possible. I'd appreciate your help.

You are getting this wrong:
First of all: please do not use any of the PowerMock... frameworks. They rely on byte code manipulation; and sooner or later that calls for trouble. Believe me, I have spent many hours hunting really strange errors for no good reasons.
Then: do not test your code this way!
You use a mocking framework to create/control those objects that you pass to your "class under test". You don't use the framework to directly test your "class under test"!
You also don't want to write test code that knows about private methods - those are implementation details.
What you do instead:
a) as said, you can use mocking to pass objects into your class under test. And then you can control/verify those mocks see the calls that you expect your "class under test" to make
b) you create objects of your "class under test" ... and then "assert" on the properties of those objects; or on results that method calls return.
Just to be precise: a mocked object ... doesn't know anything about the code in the "original" class. It is a mock! You can't use it for the kind of testing that your question implies you want to do. Either you call methods on your real class; or you specify something for a mock. But creating a mock to then "associate" it to the concrete class implementation ... is simply impossible.
Finally: if you think that your concrete class is actually "too big" to just be created the normal way for tests ... then chances are: your class is simply too big for anything else. Classes should be small; and their design should follow SOLID principles.
Long story short: don't try to force un-testable code into "tests", by using PowerMock... You better invest some more time to improve the quality of your production code; that will result in much higher "return on investment".

Related

How to mock private enum using Powermock?

I have following class:
public class MyClazz
{
private static enum MyEnum
{
INSTANCE;
private MyClazzB getMyClazzB()
{
....
return
}
final MyClazzB b = getMyClazzB();
}
public void methodWhichIWantTest(arguments)
{
//...
//here is logic which I want to test
//...
MyEnum.INSTANCE.b.doSomething();//I want to mock this line.
}
}
I am not author of MyClazz and I do not want to change anything. I only want to test methodWhichIWantTest method. The problem is that method getMyClazzB throws exception. I do not how to mock it.
How to mock it? I think that I should mock MyEnum class but it is private.
===EDIT===
I think that I should clarify my question because I got some comments.
I am not author of MyClazz but this class is part of my project and I can edit this class but I would like to avoid editing as much as possible. I fixed some bug in private method of MyClazz. I would like to write some test which tests my fix. Testing private method is not good practice so I can write integration test or write unit test for some public method which calls this private method. Firstly I wanted to write integration test but after research I found that integration test is to complicated and takes me too much time. So I decided to write unit test for some public method which calls this private method. methodWhichIWantTest is this public method. Method getMyClazzB throws exception because it crates javax.naming.InitialContext and lookup some beans (It works properly on wildfly but it does not work inside simple unit test).
I think that I have following options:
do not test it
write integration test (it is time consuming)
try to mock MyEnum and write unit test
try to mock InitialContext and write unit test
edit source code, mock and write unit test.
test private method directly using java reflection
My question is related to point 3. I do not know how to realize point 3 I was curious how to do it so I asked my question.
I am afraid that realizing point 3 is not possible within a reasonable time.
Thank you for help.
how-to-mock-an-enum-singleton-class-using-mockito-powermock does not solve my issue because MyEnum enum is a private. E.g. I cannot use #PrepareForTest({MyEnum.class}) annotation because MyEnum is not accessible.

JUnit Call a test method in one class from another class

Had a quick look at past questions, couldn't see something similar so here goes:
I also made a mistake in choosing dummy names for this example to illustrate my point, I'll rename them.
I have a class which has a JUnit test:
public class CheckFilter {
#Test
public void Run_filter_test() {
//some code
}
}
And then another class:
public class CheckVideoPlays {
#Test
public void Play_video_in_full() {
//some more code here etc
}
}
Finally, how do I call these two tests from another class, obviously you can't extend multiple classes.
public class RunAllTests {
//How do i call both
//eg
//
//Run_filter_test();
//Play_video_in_full();
}
Note: I don't want to call the class. Don't want to run as:
#RunWith(Suite.class)
#Suite.SuiteClasses({
CheckFilter.class,
CheckVideoPlays.class
})
A few things.
Change the name of Sanatize_all_inputs to the (java standard form) camel case, perhaps sanitizeAllImports. When using Java, obey Java.
It seems likely that you will sanitize inputs once per test,
which, to me, indicates that you want a class level variable of type ConvertAll in your jUnit test class.
Either use composition (another class level variable of type BaseTestBlammy) or inheritance (extend class BaseTestBlammy) to acquire access to the BaseTestBlammy methods.
Here is an example:
public MyJunitTestKapow
extends BaseTestBlammy
{
private final ConvertAll convertAll;
public MyJunitTestKapow()
{
convertAll = new ConvertAll();
}
#Test
public void someTest()
{
convertAll.sanitizeAllInputs(...);
... // do the rest of the test here.
}
}
You could make static method in ConvertAll.sanitize then call this method in both ConvertAll.Sanitise_all_inputs test and CheckFilter.Run_filter_test
As better (more maintainable and powerful) solution you may create Sanitiser class with sanitise() method (method may be static or not). Then each class that requires sanitise functionality will call Sanitiser.sanitise. This soltion may be better in long run- you may pass paramethers to sanitise method (or to Sanitiser constructor), Sanitiser may have some internal state, etc
Side note: you may consider migrating to Junit5 (basically it is just change of imported packages). Junit5 has #DisplayName annotation that declares nice test method names (with spaces). So your test methods will respect Java naming convention.
#Test
#DiplayName("Sanitize all inputs")
public void sanitiseAllInputs() {
//some more code here etc
}

Is it possible to use JMockit's Deencapsulation API to exchange method implementation?

So, basically, a there is some poor code that I cannot change that needs to be tested. Traditionally, you inject your mocked dependencies, but with this code, I cannot do so, because there are no setter methods. Worse, the function I need to test calls a bunch of static factory methods-I can't just use the MockUp strategy to swap out the implementation there, because there is no class instance to be injected at all.
In C/++, you can retrieve a pointer to a function and know it's type by it's signature. If you changed the pointer, then you could potentially change how the stack was constructed by the compiler and you could pass function's around and all that Jazz.
Is there a way to use the Deencapsulation API to replace a static method implementation? Using this, I could write my own class, descend from the traditional, but return mocked objects in order that dependency injection still be achieved?
public class TestedClass {
public static void testedMethod() {
UnMockableType instanceVariable =
UnInjectableFactory.staticFactoryConstructor();
instanceVariable.preventControlFlowInfluenceThroughMocking();
}
}
Easy enough:
#Test
public void exampleTestUsingAMockUp()
{
new MockUp<UnMockableType>() {
#Mock
void preventControlFlowInfluenceThroughMocking() {}
};
TestedClass.testedMethod();
}
Above, UnInjectableFactory isn't mocked because it doesn't need to be (assuming it simply instantiates/recovers an UnMockableType).
It could also be done with #Mocked and the Expectations API.

Guava #VisibleForTesting : Help me with a complete example

My intent is to do unit test of private methods and I understand on how to import the #VisibleForTesting and use it for a private method. I have done a quite a bit of search but unable to see a complete example that demonstrates this feature.
For eg:
class MyClass {
#VisibleForTesting
private double[] getWorkArray(double[] values,int length) {
:
:
return <some double array>
}
}
Now in JUnit, I must be able to do
#Test
public void testProvateMethod() {
MyClass object = new MyClass();
assertNotNull(object.getWorkArray(...);
}
But the difficult part is I am unable to comprehend/do the following
a) Snippet of maven compiler plugin for including the relevant annotation processor
b) Actually be able to test a private method. (since it throws error related to visibility of method)
I am unable to do it in action while I write a test in JUnit (due to the private access error). For eg: mvn clean test
Please provide a complete example to really all steps involved in getting the JUnit test of private methods done.
Firstly, I do not recommend to test private methods, unit tests should test public methods in most cases. If you have to test private methods, it usually indicates a bad design.
Regarding to #VisibleForTesting , it is used in package-methods in Guava, and not part of JUnit API. The annotation is just a tag to indicate the method can be tested, it even doesn't be loaded in JVM. So if you need to test non-public methods, make the methods package scope which is visible to unit test classes in same package.
Last, by using reflect can access private methods, if you really have to test them.
Testing a private method must be one of the bad patterns.
However, there are times when you often feel the urge to test private methods.
In this case, I personally use ReflectionTestUtils to test the method. This is because we wanted to keep the original intent of the private method, and only test the method. Below is an example of my sample.
MyClass myClass = new MyClass();
ReflectionTestUtils.invokeMethod(myClass, "getWorkArray", values, length);
One drawback is the fact that I get the name of the method as a String and it is quite a bit sad except for the fact that refactoring does not convert correctly in IDEA.
I hope it helps.
Thanks.
You can remove private keyword:
class MyClass{
#VisibleForTesting double[] getWorkArray(double[] values,int length) {
:
:
return <some double array>
}
}
Then you are able to:
MyClass object = new MyClass();
assertNotNull(object.getWorkArray(...);
in your test.

Listening for when a method is called in a class, and then possibly overriding it (java)

So, let's say I have 2 classes, Foo1 and Foo2, which is in a separate library.
Foo2 is a class that is already instantiated, and I cannot correctly reinstintate it as a subclass to override a method in Foo2.
Is there any way I can listen to a certain method that is called in Foo2, and then possibly cancel the execution of said method, and from there create another method. I understand if what I"m saying is confusing, hopefully I can get some help :).
class Foo{
void x(){
if (Foo2.x2().called){
//do stuff
}
}
}
class Foo2{
void x2(){
//Stuff done here...
}
}
Obviously, the above code won't do anything, it is just simple an example of what I am looking for.
you need a proxy on that object, and an interceptor on the method. There are a couple of ways to do it:
If you have an interface you can use reflection and proxies and invocation handlers docs.oracle.com/javase/6/docs/api/java/lang/reflect/Proxy.html.
If you have a concrete class you can use CGLIB cglib.sourceforge.net to create an enhancer for your class
If you are using Spring you can use the AOP http://static.springsource.org/spring/docs/2.5.5/reference/aop.html.
You can also use AspectJ http://www.eclipse.org/aspectj/doc/next/progguide/ to do the same
Cheers!
If you can't somehow subclass Foo2 or modify the existing lib (in worst case you could decompile/modify/recompile) you could use aspectj to intercept calls.
You'd probably want to use load-time weaving for this purpose. Check out the general documentation for load-time weaving here: http://www.eclipse.org/aspectj/doc/next/devguide/ltw.html. It's a fairly involved procedure to add/configure aspectj though so I'd only recommend it as a last resort
Depending on what you're trying to do, this might work:
If you had a boolean isX2Called in class Foo, when x2() is called, set isX2Called to true. Then in x(), you can check if isX2Called is true. If you ever want to reset, you can set isX2Called back to false. This might not work for all purposes though.
In my opinion, to solve this issue you could use a third class to act as a Decorator/Proxy.
For instance, you can do something like:
class FooManager {
private Foo1 f1;
private Foo2 f2;
private boolean canExecuteFooMethods(){
// Evaluate if should run any Foo1 or Foo2 method
}
public void foo1Method(){
if(canExecuteFooMethods()){
f1.x();
}
}
public void foo2Method(){
if(canExecuteFooMethods()){
f2.x();
}
}
}
Assuming that you can subclass the type, the following code would work perfectly:
Foo foo = new Foo() {
#Override
public void someMethod() {
super.someMethod();
//your logic here (listen, hook, spy, override, etc)
}
}

Categories

Resources