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.
Related
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.
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()
}
}
I am using jmockit to mock my classes for unit test purpose. Everything is working fine so far.
I have a factory which is thread safe and singleton as shown below:
So for below class, I am able to get 50% Line Coverage because I am not able to cover private constructor TestFactory().
public class TestFactory {
// not able to cover this
private TestFactory() {}
private static class TestHolder {
private static final TestClient INSTANCE = new TestClient();
}
public static IClient getInstance() {
return TestHolder.INSTANCE;
}
}
My question is - Is there any way I can cover TestFactory() private constructor so that I can get 100% Line Coverage in my Cobertura Report for this class?
Invoke it using reflection or just mockit.Deencapsulation.newInstance(). Write a test method like this
#Test
public void privateConstructorCoverage() throws Exception {
Deencapsulation.newInstance(TestFactory.class);
}
Deencapsulation javadoc
Provides utility methods that enable access to (ie "de-encapsulate") otherwise non-accessible fields, methods and constructors belonging to code under test.
Is there a way to invoke a private static method of an enumerated singleton? For example, say I have some legacy code that I need to test which has the following structure:
public enum Singleton {
INSTANCE;
private static double methodToTest() {
return 1.0;
}
public static String extremelyComplexMethod() {
methodToTest();
//Imagine lots more complex code here
return "";
}
}
How would I go about creating a class that tests methodToTest in isolation? I've tried reflection using Whitebox (included in PowerMock) but I've had no luck. Is there a way to do it?
I know that testing a private method directly is not the prefered method of doing things, but I want to know if its possible to test the private method directly. I tried to get the code to get recognized as java, but I was unsuccessful.
I was able to invoke the method try this following code
#RunWith(PowerMockRunner.class)
#PrepareForTest(Singleton.class)
public class MySingletonTest {
#Test
public void test() throws Exception{
Whitebox.invokeMethod(Singleton.class, "methodToTest");
}
}
Don't forget to add the Singleton class in PrepareForTest
I'm trying to mock a class that looks like below
public class MessageContainer {
private final MessageChain[] messages;
MessageContainer(final int numOfMessages, final MessageManagerImpl manager, final Object someOtherStuff) {
messages = new MessageChain[numOfMessages]
// do other stuff
}
public void foo(final int index) {
// do something
messages[index] = getActiveMessage();
}
}
My test code would be as followed:
#Test
public void testFoo() {
MessageContainer messageContainer = Mockito.mock(MessageContainer.class);
Mockito.doCallRealMethod().when(messageContainer).foo(anyIndex);
}
I got a NullPointerException since 'messages' is null. I tried to inject the mock by using #InjectMocks, however this case is not supported since not every parameters of the constructor are declared as members.
I also tried to set the 'messages' field by using WhiteBox
Whitebox.setInternalState(messageContainer, MessageChain[].class, PowerMockito.mock(MessageChain[].class));
but I got a compile error since setInternalState only supports (Object, Object, Object) and not Object[].
Is there any possible way to mock a private final field?
Thank you guys in advance.
Based on your edits and comments, I would say mocking this class and verifying the method was invoked is sufficient.
If it is third-party code, you should rely only on its method signature, which comprises the class's public API. Otherwise you are coupling your tests too tightly to something you have no control over. What do you do when they decide to use a Collection instead of an array?
Simply write:
MessageContainer container = mock(MessageContainer.class);
//Your code here...
verify(container).foo(obj);