I recently started working on TDD for exisitng project and faced couple of issues, one of those is mentioned below
I have a private variable to be mocked in test class and the variable looks like below
private Class<XYZ> cls = XYZ.class;
later this "cls" variable is used as arugment for one of the method as className
private List create(Class className, Object objectTO, List<String> names)
I know private variables can be mocked and I mocked the private variable in my test case by following below steps
java.lang.reflect.Field;
Field field = PowerMockito.field(XYZ.class,"cls");
field.set(XYZ.class, "objectOfXYZClass");
When i run my test class,i'm getting below error
java.lang.IllegalArgumentException: Can not set java.lang.Class field com.tools.XYZ.cls to java.lang.Class
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:75)
at java.lang.reflect.Field.set(Field.java:680)
Please can someone help me out on this and let me know what i'm missing.
PS: I used @preparefortest
and mentioned all the required classes in that and running my test class using @runwith(powermockrunner.class)
You are getting unit tests wrong. They are not about testing internal implementation (like fields or private methods).
Unit tests should typically do only the following things:
In other words: you very much want to only test on the externally visible behavior of your "class under test". And you know: if your class has no externally visible behavior - why do you have than in the first place?!
Of course, sometimes that isn't "good enough". In that cases, what you typically do: you turn to some mocking framework (like EasyMock or Mockito) to create mocked objects. You use these mocks when instantiating your class under test (called dependency injection). By doing so, you get full control over your class under test; for example you can verify that your mocks see those method invocations that you would expect.
So, long story short: yes, it would be possible to somehow access fields of your class under test. But that leads to unit tests that are not worth that name. Because those tests break as soon as you start refactoring the internals of your code. In that sense: such tests are only good to prove that your current implementation works as expected. But any time you change something, you will have to rework (probably larger!) parts or your test code.
Finally: writing unit tests is a skill that needs to be learned. One of the best resources to get there are those videos.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With