PowerMockito mocking static class INSIDE enum? - java

I have a enum that has to have a inner static class for bean injection.
I feel I'm facing the most difficult situation for a mock: enum, static class, static field, static method..
public enum Category{
C1(Something(Constants.getFactory().createSomething(""))),
C2(...);
public static Constants {
#Autowired
private static Factory factory;
public static Factory getFactory(){
return factory;
}
}
}
And my testing class using PowerMockito is:
#RunWith(PowerMockRunner.class)
#PrepareForTest({Category.class,Category.Constants.class})
public class CategoryTests {
#Before
public void setUp() throws Exception {
PowerMockito.mockStatic(Category.class);
PowerMockito.mockStatic(Category.Constants.class);
//This simply testing mock didn't work
//PowerMockito.when(Category.Constants
// .getFactory()).thenReturn("123");
//I tried to mock the inner field 'factory' and use it directly without a getter
//(with small changes in the original class)
//But it didn't work either
Factory factory = PowerMockito.mock(Factory.class);
NewClass newClass = PowerMockito.mock(NewClass.class);
PowerMockito.when(Factory.createSomething(anySring()))
.thenReturn(newClass);
Whitebox.setInternalState(
Category.Constants.class,"factory",Factory);
//This is like the most common way to stub
//It didn't work, so I believe the inner static class were never mocked
PowerMockito.doReturn(factory).when(Category.Constants.class,
"getFactory", anyString());
}
//I don't know if real test cases matter that much but I update to add it for reference.
#Test(dataProvider = "Case1")
public void testFromFilterType(final String testName, String input, final Category expected) {
assertEquals(Category.doSomething(input), expected);
}
#DataProvider(name = "Case1")
Object[][] fromFilterTypeCases() {
return new Object[][] {
{ "C1", "input1", Category.C1 },
{ "C2", "input2", Category.C2 },
};
}
}
//Currently the tests got skipped because in class Category Constants.getFactory().createSomething(""),
//where Constants.getFactory() returns null and mocking doesn't work.
At first I didn't mock the Enum, but just the static inner class. After heavily searching, I tried in all ways. The setup seems correct but it may miss some tricks. Any helps?

A bit of guessing: Category.class is the class you intend to test. That class itself contains nothing that should require mocking/preparation.
So: drop these parts in your code. Even if it doesn't cause your current issue, I am pretty sure that it might have all kinds of unwanted consequences when you start testing things later on.
Beyond that, the real answer would be to avoid the necessity for PowerMock(ito) in the very first place. You are already using #Autowired, which implies that you are using a DI framework. Most DI frameworks also have hooks for unit testing. So you should rather try to get #Autowired to work in your test setup.

Related

Unit testing a function that is calling another static function in android java using Mockito

I have a scenario where I call a static function from another function. How can we write unit tests in such cases?
Here is my code:
public class TradesHelper {
public static double calculatePL(Market market, Trade trade) {
double pl = (Helper.priceDifference(market, trade) / market.getSize()) * trade.getQuantity() * Helper.effectiveValue(market);
return pl;
}
}
public class Helper {
public static priceDifference(Market market, Trade trade) {
//Do something here
}
}
This is how I am trying to write unit test case:
I have written a unit test case for Helper class. But for TradesHelper class this is how I am trying to write:
public class TradesHelperTest {
#Mock
Market market;
#Mock
Trade trade;
#Test
public void calculatePlFromPips_Test() {
//Trying to return a value when priceDifference function in Helper class is called
Helper helper1 = spy(new Helper());
doReturn(0.0012999999999999678).when(helper1).priceDifference(new Market(),new Trade());
}
But I am getting thus error:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
I am new to writing unit tests. Can someone guide me on how to do it write?
Thanks
As the comments tell you cannot mock static methods with pure "vanilla" Mockito.
But static access is a bad design and should be avoided. You problem creating a test is the prove that static access makes the code using tightly coupled and therefor hard to reuse (since testing is kind of "reuse"...).
Static access also effectively prohibits inheritance and polymorphism, two major concepts why we are using an OO language.
On the other hand there is not rule that "helper classes" or "utility classes" (in the sense that they provide common behavior) must have static methods. This is only a misconception because classes with only static methods used to be called "utility classes".
So instead of surrendering to your bad design and using Powermock you should change both class Helper and class TradesHelper to have non static methods and use objects of them in your production code.
Java is an object oriented programming language after all, so why avoiding objects?
But do not instantiate Helper inside TradesHelper. Pass the instance of Helper in as a constructor parameter:
public class TradesHelper {
private final Helper helper;
public TradesHelper(Helper helper){
this.helper = helper;
}
public double calculatePL(Market market, Trade trade) {
// ...
public class TradesHelperTest {
#Mock
Market market;
#Mock
Trade trade;
#Mock
private Helper helper;
private TradesHelper tradesHelper; // class under test, no mock nor spy!
#Before
public void setup(){
tradesHelper= new TradeHelper(helper);
}
#Test
public void calculatePlFromPips_Test() {
// arrange
doReturn(0.0012999999999999678)
.when(helper)
.priceDifference(market,trade);// use mocks here not new objects
// act
tradesHelper.calculatePL(market,trade);
// assert
// either assertThat() or verify()
}
}

Powermock - mocking static class members

I'm trying to mock the following class which contains some static members
public class ClientFact {
private static final String BASE_URL = Config.getProperty("prop1");
private static final String USERID = Config.getProperty("prop2");
......................
public static Client createClient() throws AppException {
}
}
but i'm running into issues with the static member variables which are populated by Config.getProperty. This class does a read on a properties file like so
public class Config {
...............
public static String getProperty(Param param) {
String value = null;
if (param != null) {
value = properties.getProperty(param.toString());
}
return value;
}
}
I'm trying to mock this call since i dont care about the loaded properties in my test. This is what ive tried
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClientFact.class})
public class MyTests {
#Test
public void test() {
PowerMock.mockStaticPartial(Config.class, "getProperty");
EasyMock.expect(Config.getProperty(EasyMock.anyObject())).andReturn(EasyMock.anyString()).anyTimes();
PowerMock.mockStatic(ClientFact.class);
}
}
but its giving the following error...
java.lang.NoSuchMethodError: org/easymock/internal/MocksControl.createMock(Ljava/lang/Class;[Ljava/lang/reflect/Method;)Ljava/lang/Object;
at org.powermock.api.easymock.PowerMock.doCreateMock(PowerMock.java:2214)
at org.powermock.api.easymock.PowerMock.doMock(PowerMock.java:2163)
any ideas what im doign wrong here?
A non-answer: consider not making static calls there.
You see, that directly couples that one class to the implementation of that static method in some other class; for no real reason. (and for the record: it seems strange that a USER_ID String is a static field in your ClientFact class. Do you really intend that all ClientFacts are using the same USER_ID?!)
You could replace that static call with a non-static version (for example by introducing an interface); and then you can use dependency injection to make an instance of that interface available to your class under test. And then all your testing works without the need to Powermock.
Long story short: very often (but not always!) the need to turn to Powermock originates in production code which wasn't written to be testable (like in your case). Thus instead of using the big bad Powermock hammer to "fix" your testing problem, you should consider improving your production code.
You might want to listen to those videos to get a better understanding what I am talking about.

In a JUnit test is there a rule to set the subject of the test

I've been writing a lot of JUnit tests lately and see this same boilerplate pattern.
public class MathOpTest {
private MathOp a;
#Before
public void setUp(){
a = new MathOp();
}
...
}
Is there an annotation to set this up for me as I always need to write a setUp method and it usually only has the single class I'm testing.
Something like:
public class MathOpTest {
#TestSubject
private MathOp a;
...
}
You can assign the fields when they are declared:
public class MathOpTest {
private final MathOp mathOp = new MathOp();
...
}
This is simple and straight-forward, so I recommend that you assign fields in your test class at declaration time whenever possible (certainly in the case you gave).
If you want to understand a bit more, read on.
JUnit will create a unique instance of your test class for each test method, so even if your test modifies internal state of MathOp, using fields this way is safe as long as your tests don't modify global state.
For JUnit4-style tests (i.e. tests that do not extend junit.framework.TestCase) JUnit will create the test class just before the test method is run, and make it eligible for garbage collection after the test method completes.
Use #Before methods for more complex initialization.
Usually I use #Before when:
Initialization of the field is complex
Initialization of the field requires calling code that is declared to throw a checked exception
You need to do initialization after a #Rule has been applied (for instance, injecting a mock into a constructor)
Usually you would create the object under test in the test method when the class needs to be constructed different ways for different use cases.
Examples
Here is an example of using #Before and initMocks():
public class MathOpTest {
#Mock private Calculator mockCalculator;
#Mock private Supplier<Double> mockPreviousResultSupplier;
private MathOp mathOp;
#Before
public void createMathOp() {
MockitoAnnotations.initMocks(this);
mathOp = new MathOp(
mockCalculator, mockPreviousResultSupplier);
}
...
}
Here's an example of a #Before method that uses the result of a #Rule:
public class MyWriterTest {
#Rule public final TemporaryFolder folder = new TemporaryFolder();
private File output;
private MyWriter writer;
#Before
public void createMyWriter() {
output = folder.newFile();
writer = new MyWriter(output);
}
...
}
Aside: I personally wouldn't recommend using #InjectMocks to create the class you are testing. It's too much magic for my taste. Having an explicit constructor is cleaner and simpler, and I like my tests to be clear and simple :-)
Nothing like this directly exists in vanilla JUnit to my recollection. Most people elect to either initialize their test subject in a #Before statement, or inside of their tests. In its defense, it makes it clear what is being established before the tests are run, and it always resets the state of your test object.
If you're using Mockito, you actually do have the benefits of declaring a class and annotating it with #InjectMocks to both instantiate the class and inject whatever #Mock classes you had prior.

Mockito NotaMockException

I am facing an issue with Mockito junit testing. I am new to it and am a bit confused with the problem I am facing. Any help on this would be appreciated.
class Activity{
public void firstMethod(){
String str = secondMethod();
}
public String secondMethod(){
String str = null;
/* some Code */
return str;
}
}
Getting exception :
*org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!*
in the below code
class ActivityTest(){
Activity act;
#Before
public void setup(){
act = new Activity();
}
#Test
public void testFirstMethod(){
Mockito.doReturn(Mockito.anyString()).when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
I am aware that activity is not a mock but I am not sure for a way around this as secondMethod() is a method in the same class. I need to write rule for secondMethod() as I have already done its Unit Testing. The definition of secondMethod() consists has external dependencies. Should I be mocking the external dependencies present in secondMethod() and writing rules for them rather than rule for secondMethod()?
I found this post:
Mockito Spy'ing on the object being unit tested
However separating the secondMethod() into a different class does not make sense. My method is related to this class. Creating a different class for testing does not seem right to me. Even mocking the actual class using spy() is not the most correct way as already explained in the post.
I don't think I should be creating a mock of the Activity class as that is the class I am testing. I would really appreciate help and insights into this.
As you noted, act is not a mock, and therefore you cannot record behavior on it. You could use Mockito.spy to, well, spy (or partially mock) the act object so that you only record the behavior of secondMethod and execute the actual code for firstMethod.
Note, however, that matchers can't be used in doReturn calls regardles of how you're mocking or spying your object. A return value must be a concrete object.
class ActivityTest() {
Activity act;
#Before
public void setup(){
act = Mockito.spy(new Activity()); // Here!
}
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
A slightly more elegant syntax allows you to use annotations instead of explicitly calling Mockito.spy, but it's a matter of taste really:
#RunWith(MockitoJUnitRunner.class)
class ActivityTest() {
#Spy
Activity act = new Activity();
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
There is no reason to mock anything in this example. Since there are no dependencies and both methods are public, you can test them directly.
public class ActivityTest() {
private Activity act = new Activity();
#Test
public void testSecondMethod(){
assertEquals("expected-value", act.secondMethod());
}
#Test
public void testFirstMethod() {
act.firstMethod();
// success if no exception occurs
}
}
Since firstMethod does not have any detectable effect on the Act instance, nor on any dependency (since there are none) you can simply call the method and be satisfied if no exception is thrown. One could also reason that such a method should not be tested at all.
I assume the example given is a simplification of a class where calling firstMethod actually does have side effects, who knows...
Here are some hints:
Mock the Activity.
Tweak the behavior of secondMethod with when / then / doReturn
Use doCallRealMethod when firstMethod is invoked.
Hope it helps.

Mocking autowired field in the method

I was wondering whether there's a way to mock the field which is being autowired.
Consider the following case.
I have a class name A
public class A {
#Autowired
private B b;
public void aMethod() {
b.method();
}
}
The other class B looks like this
public class B {
public void method() {
// some code
}
}
Now i want to write junit for the method.
I know there's a way to mock the autowired field like this.
public class TestA {
#InjectMock
private A a;
#Mock
private B b;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
public void testAMethod() {
// write test case.
}
}
But my question is -> Is there a way to mock the autowired field inside method after creating object with new.
eg
public class TestA {
public void testAMethod() {
A a =new A();
// how to mock the B instance in it.
}
}
Please suggest or there's no way to do this????
I dont want to change from private modifier. Nor i want to add getter's and setters or reflection. I just want to know is there a way to mock the B instance after creating the new object of A class.
How about ReflectionTestUtils?
A a = new A();
B b = mock(B.class);
ReflectionTestUtils.setField(a, "b", b);
It's still reflection-based and has all related drawbacks, though it's quite simple and easy to read.
You can not do that with mockito, this would require to modify the bytecode of the class being tested. However Powermock allows such stubs. Note though that I and the creator of Powermock - Johan Haleby - would push for a refactoring instead of using Powermock. Powermock is very powerful, maybe too much, and working allows anyone to write legacy code, that would be difficultly maintainable or extensible (property you can find in poorly designed legacy code).
In your case I don't know what's wrong in your case with the dependency injection. However if the code need a new instance of B, it may be useful to have inject in A a factory/provider/builder class which will make a new instance of B. Such code can be easily stubbed with Mockito.

Categories

Resources