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.
Related
I meet a question about the mock private method in a injected mock annotated class. My code is like following
public class foo {
#Autowired
fooBean fooBean;
public void method1() {
this.method2();
}
private void method2() {
fooBean.someMethod();
system.out.println("Hello world");
}
}
when I create a UT class with powermockito, the foo class should be #injectMocks, since the fooBean should be injected as mock class. But when foo class is marked as #injectMocks, it can't be mock its private method using like "doReturn("xxx").when(foo,"method2")", it will raise error about this can not be applied to injectMocks.
It is blocked. Don't know how to continue.
TLDR; you cannot use InjectMocks to mock a private method.
You should mock out implementation details and focus on the expected behaviour of the application. It is important as well that the private methods are not doing core testing logic in your java project.
Focus on writing functions such that the testing is not hindered by the private method. If it is not possible, it is worth asking what is the private method doing that is so valuable to your function and why it has to be private.
There are other ways to test private methods - You could use the Reflections java library, this would let you stop methods at runtime and inject specific values into them. But, again, this is finding a solution to a problem that does not need to exist.
Is it possible to instantiate a class with a complex constructor without mocking or calling its constructor? This would be useful because the unit test class shouldn't need to change every time a new dependency was added to the service.
Mocking the service solves the problem by creating a new implementation of the class, with empty method overrides, but this isn't an instance of the implementation. This is a problem because any time a method in the mocked service is called, Mockito has to be told to call the real method. Instead, an actual implementation of the service would be preferred.
For example:
class ComplexService {
private Service service1;
private Service service2;
private Service service3;
private Service service4;
private Service service5;
ComplexConstructor(Service service1, Service service2, Service service3, Service service4, Service service5) {
this.service1 = service1;
this.service2 = service2;
this.service3 = service3;
this.service4 = service4;
this.service5 = service5;
}
boolean methodToTest() {
return service1.get();
}
}
In the unit test class, is it possible to have an instantiation of a implementation without having to call its constructor?
public class ComplexConostructorTest {
private ComplexConstructor complexConstructor;
private Service serviceMock;
#Before
public void init() {
/*
Somehow create implementation of complexConstructor
without calling constructor
. . .
*/
// Mock dependency
ReflectionTestUtils.setField(complexConstructor,
"service1",
serviceMock = Mockito.mock(Service.class));
}
#Test
public void service1Test() {
when(serviceMock.get())
.thenReturn(true);
assertTrue(complexConstructor.methodToTest());
}
}
Edit
It is possible using reflection, I was hoping there was a built in way in JUnit or Mockito to achieve the same thing. Here is how to do it using reflection.
#Before
public void init() {
Constructor<?> constructor = ComplexConstructor.class.getConstructors()[0];
complexConstructor = (ComplexConstructor) constructor.newInstance(new Object[constructor.getParameterCount()]);
// Mock dependency
ReflectionTestUtils.setField(complexConstructor,
"service1",
serviceMock = Mockito.mock(Service.class));
}
This is not possible, as far as I know, but you can simply add a simpler Constructor to your class and use that for testing. On the other hand, if the test tests the object in a state that is different to what it will be in the app, I'm not sure how good such a test would be.
You can, but you probably don't want to:
ComplexConstructor partialMock =
Mockito.mock(ComplexConstructor.class, CALLS_REAL_METHODS);
This "partial mock" instance will not have its constructor or field initializers called, but all calls to the system under test will invoke the class's real behavior. (Technically the class will also have its equals and hashCode overridden for Mockito's purposes, and the class will be a generated subclass of ComplexConstructor instead of ComplexConstructor itself.)
In this way, you can be insulated from the constructor, but because you are suppressing an arbitrary subset of the class-under-test's behavior it is much more difficult to determine exactly what you're testing in order to be confident the system works because the test passes. That should be your main goal in testing, and it may be difficult to achieve that with partial mocks. Colleagues or collaborators may rightly observe that you shouldn't mock your system under test for exactly this reason.
Though personally I don't think it's wrong or unexpected for you to need to change your unit tests to supply mocks when needed, you could create a factory separate from your test that supplies testing instances of ComplexConstructor, or consider using a dependency injection framework that automatically supplies mocks to your system under test.
Looks like you are mixing up several terms and concepts. Let me help you understand them better.
This would be useful because the unit test class shouldn't need to change every time a new dependency was added to the service.
Your class has a number of dependencies, that are provided via the constructor. If you are writing unit test your aim is only to test this dependent class, all dependencies should be mocked. That's why it is called unit testing. This means that with every new dependency of your class the test should be updated by adding new mock and its mocked behaviour.
Mockito has to be told to call the real method. Instead, an actual implementation of the service would be preferred.
Consider integration tests, in this case, you can mock only some amount of dependencies while others will work as intended or "real" until you mock them of course. However, if you want just to avoid supporting tests then it is not the right approach.
Please don't try to hack your tested class from your test by reflection. This can lead to wrong test results, waste of time and overall disappointment :) Mocking libraries like PowerMock and JMockit provide any kind of hacks, like ones you've tried to implement yourself and are in general too powerful.
With Great Power Comes Great Responsibility
You can create helper methods as part of your test code, for example some factory methods with descriptive names that construct the object. For example, make_default_ComplexService and more the like, just as needed by your tests. The tests could then use these methods, and if the constructor changes, you will in many cases only have to update the helper methods and not all of the tests. This approach is generic enough to also separate your test from drastic changes like turning the "constructor with parameters" approach into the "non-argument constructor with lots of setters" approach.
This approach will reduce maintenance effort for your tests, you will still use the original constructor (because it is called by the factory) rather than some fake constructor, and your test code might even be more readable than with the direct constructor's calls if the factory methods' names are well chosen.
You could add a parameterless constructor to your class and create setter for all your fields.
class ComplexService {
private Service service1;
private Service service2;
private Service service3;
private Service service4;
private Service service5;
public ComplexService(){
super();
}
...
public void setService1(Service service1){
this.service1 = service1;
}
//for other fields too
...
}
In your test you call it like:
myService = new ComplexService()
myService.setService1(service1);
...
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".
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.
I am using mockito for mock the unit test cases and am getting the following exception
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type ConsumerImpl and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMetenter code herehod();
and my code is
MessageConsumer mConsumer = Mockito.mock(MessageConsumer.class);
String data = "new Message for Testing";
Message message = new Message(data.getBytes());
Mockito.when(mConsumer.next(10, TimeUnit.SECONDS)).thenReturn(message);
StringParserTest parserTest = new StringParserTest();
ConsumerImpl<String> consumer = new ConsumerImpl<String>(mConsumer, parserTest);
String mes=Mockito.verify(consumer,VerificationModeFactory.times(3)).consumeMessage(10,TimeUnit.SECONDS);
Please some one help me to solve this problem
Thanks in Advance
SRN
Well, that's exactly what mockito says, you are not passing a mock to verify !
ConsumerImpl<String> consumer = new ConsumerImpl<String>(mConsumer, parserTest);
String mes=Mockito.verify(consumer,VerificationModeFactory.times(3)).consumeMessage(10,TimeUnit.SECONDS);
Plus if you verified a mock why would you want to store the result of the invocation you verify, it wouldn't make sense since the consumer is mocked. Verify is to verify calls on mocked objects that are the collaborators of your unit tested object. Which in your case is not really clear.
Also you never use your mock mConsumer instance.
You should definitely separate your test in 3 phase, one for the fixture, one for the action, and one for the verifications. Use the BDD terminology to achieve that, it augments understanding and readability for the tester and future reader of this code (And Mockito offers them in the API through BDDMockito).
As I don't really get what the code is trying to test from the code you gave, I'll be imagining things. So for example you'll write this kind of code (using import static) :
// given a consumer
MessageConsumer message_consumer = mock(MessageConsumer.class);
String the_message_data = "new Message for Testing";
given(message_consumer.next(10, SECONDS)).willReturn(new Message(the_message_data.getBytes()));
// when calling the client of the customer (which is the unit that is tested)
new MessageProcessor(message_consumer).processAll();
// then verify that consumeMessage is called 3 times
verify(message_consumer, times(3)).consumeMessage(10, SECONDS);
Remember Mockito helps you focus on interactions between objects — as it's the most important notion of object oriented programming — and especially between the tested one and his collaborators that will certainly be mocked.
Usually we mock using #InjectMock and we try to verify a method called from inside the test case method.
Here is one scenario which generally give issue.
public class A{
#Autowired
Service s
public void method1(){
method2();
}
public void method2(){
s.someMethod();
}
}
public class ATest{
#InjectMocks
A a;
public void testM1(){
a.method1();
Mockito.verify(a, Mockito.times(1)).method2();
}
}
This will always give "NoAMockException while Mockito.verify"
instead of that we should use following verification.
public class ATest{
#InjectMocks
A a;
#Mock
Service s
public void testM1(){
a.method1();
Mockito.verify(s, Mockito.times(1)).someMethod();
}
}
Or if we want to verify() method2()
then we have to #Mock class A instead of #InjectMock