PowerMockito.whenNew is not creating mock actual instance is created - java

I have a constructor call in my method under test. I want to mock it because tries to launch a UI. I have mocked the input for constructor as well but still it is trying to create actual instance.
Production Code :
public void methodToTest() {
SaveAsDialog sd = new SaveAsDialog(getSite().getShell());
sd.setOriginalFile(file);
sd.open()
}
Test Code :
Shell mockShell=Mockito.mock(Shell.class);
IEditorSite site = Mockito.mock(TestEditorSite.class);
Mockito.when(site.getShell()).thenReturn(mockShell);
SaveAsDialog dialogMock=Mockito.mock(SaveAsDialog.class);
PowerMockito.whenNew(SaveAsDialog.class).withArguments(site.getShell()).thenReturn(dialogMock);
am I missing any thing here, when SaveAsDialog sd = new SaveAsDialog(getSite().getShell()); line is called it is creating actual instance.
I am running my test with
#RunWith(PowerMockRunner.class)
#PrepareForTest({SaveAsDialog.class})

You should pass in the instance of SaveAsDialog into your class under test as constructor parameter. This would make mocking it quite easy using plain Mockito.
If you rather want to surrender to your bad design you have to use PowerMock correctly which means you also have to preparer your class under test for mocking:
#PrepareForTest({SaveAsDialog.class,YourTestedClass.class})

Related

How can I pass a dynamic parameter-that I will create with some random library- in testNg xml?

I want to pass a dynamic parameter to a test case from testng xml, my parameter is something like:
String dynamicParameter=generateRandomStringForMail();
Here is my testcase:
#Test()
public void customerCreatorAllProducts () throws Exception {
setup();
Functions.pages.LoginPage login = PageFactory.initElements(driver, Functions.pages.LoginPage.class);
login.navigateRegisterPage().createFixedPasswordCustomerRequiredFields(dynamicParameter);
}
I will be using this parameter in other cases as well, how can i do this from testng.xml or with something else?
I am not familiar with testing.xml, but Mockito immediately comes to mind for this: http://mockito.org.
add Mockito to your project (e.g. through the build.gradle page)
add the import to your test file:
import static org.mockito.Mockito.*;
within your test class, create a mock of the class which has the generateRandomStringForMail() method. In my current project, I have
DefaultFileService mockFileService = mock(DefaultFileService.class);
define what you want the method to return under these test conditions, e.g.
when(mockFileService.generateRandomFileName()).thenReturn("fileName");
Whenever your tests need to use the result of the method in question, you can use "fileName", because you have told the test environment to give this response. My project has a method to update the image file associated with an inventory item, which process includes using the DefaultFileService to generate a random file name, then passing the image file and the new file name to the DefaultFileService to save the file in the system. My test code can't see or guess what file name would actually be produced, but my 'when' line above has resolved that problem for the purposes of testing my QuiltController class:
quiltController.update(data, mockFile);
verify(mockFileService).save(mockFile, "fileName"); // confirms the save() method was called with the expected parameters
It feels pretty similar to what you are trying to do, so hopefully that helps you proceed if you do want to explore Mockito. Don't be surprised if you need to refactor some of your work to make it more testable. I did, and have better code as a result. Give it a go :)

How to set Mock to have a default behavior and can override it in some test

I want to mock a dependency and return a default value in most test cases since most of them should not care about the values returned but there are some certain cases like I would like to test like the dependency returns some weird values or just throw. So I am modeling it in this way. Most cases, it should return a nice and valid value.
Test Setup which return the 20L by default for all test classes.
Dependency dependency = Mockito.mock(Dependency.class);
when(dependency.returnSomeVal()).thenReturn(20L);
In a specific test cases class, I would like to override the behavior like below:
when(dependency.returnSomeVal()).thenThrow(); //failure cases
when(dependency.returnSomeVal()).thenReturn(Weird_Val); //failure cases
But I don't find a good solution to override the existing behavior? Any idea?
You can reset the mock and add behavior. In the test, do
Mockito.reset(dependency);
when(dependency.returnSomeVal()).thenThrow(); //failure cases
when(dependency.returnSomeVal()).thenReturn(Weird_Val); //failure cases
Resetting will remove all mocked behavior on this class though. If you want to remock only some methods, then you have to create the mock from scratch.
I ended using myself this pattern to mock a bunch of methods of a class providing configurations.
In a #Before method I setup a bunch of stubs for a mocked object that provide a correct configuration for each test. Afterwards, in each test it was extremely convenient to only override one of those stubs to provide a different configuration and test a different error case.
I think the response from Hari Menon is correct but it somehow defeats the purpose explained in the question. If the mock is reset, all the stubs would need to be added again, making this pattern very confusing (it would be better to not use any overriding than using reset in this case, the code would be way more straightforward).
The comments added to the question provide indeed an indirect answer on how to achieve this, and why it works, but it took me a bit to get it working.
In spite of one of the comments, I made everything work by using in my #Before fixture when().thenReturn() and overriding the concrete stub with doReturn().when()
Example:
public class WorkerTest {
private ConfigProvider mockedConfigProvider = mock(ConfigProvider.class);
#Before
public void setup() {
// Setup stubs with a correct config
when(mockedConfigProvider.getValue("property1")).thenReturn("value1");
when(mockedConfigProvider.getValue("property2")).thenReturn("value2");
when(mockedConfigProvider.getValue("property3")).thenReturn("value3");
when(mockedConfigProvider.getValue("property4")).thenReturn("value4");
}
#Test
public void test_GoodConfig(){
// The config object gets injected in the test worker
Worker testWorker = new Worker(mockedConfigProvider);
// testWorker.execute() returns true if everything went well
assertTrue(testWorker.execute());
}
#Test
public void test_BadConfigProp1(){
// Test now with a broken 'property1', overriding that stub.
doReturn(null).when(mockedConfigProvider).getValue("property1");
Worker testWorker = new Worker(mockedConfigProvider);
// testWorker.execute() returns false if there is a problem.
assertFalse(testWorker.execute());
}
#Test
public void test_BadConfigProp2(){
// This test needs to only override the result of property2
doReturn("crazy result").when(mockedConfigProvider).getValue("property2");
...
}

When you mock a class in mockito framework, do you stand up actual mock class manually?

I am fairly new to mockito framework. I've been reading upon multiple tutorials in regards to it. One of them I was following is this: https://www.tutorialspoint.com/mockito/mockito_first_application.htm
There is a statement creating a mock of Stock Service.
In this example, we've created a mock of Stock Service to get the dummy price of some stocks
My question is Stock Service is a real service class or mock service class you have to manually stand up for mimicking the real service class. I am a bit confused. Having basic understanding of junit framework. What I had practiced before was if there is a service class Foo then I used actual class that provides all the exposed methods.
public class Foo {
public Foo() { } // construtor
public String returnAddress(String userId) {
// ...
return dataAccesobj.getAddress(userId);
}
}
Calling foo.returnAddress(..) in unit test if I remember right.
The reason I am asking this question is while I was working with mockitoto create a test method for a class, I ran into a unique(?) challenge.
I started with a real service class which depends on its super class constructor to return its instance. The challenge I ran into was this super class constructor initiates DB connection and loading/parsing properties files which I do not need for my test. I was thinking about how to prevent DB connection and loading/reading prop files....
I thought I read from one of mockito tutorials you can isolate testing without having such services. I tried with #Mock and #Spy (not fully understanding well still what they are for..) but it didn't make a difference for output (maybe I misused those annotations).
So what I did was actually creating fake/mock class out of real service class (e.g. Foo) by simply copying it and renamed it as FooMock and put it in src/test/java folder in where unit test class is running from. I kept the mock class exactly same as the real service class except taking out unwanted logic such as db connection or loading/reading prop file for env specific. By doing that I was able to test one of exposed methods that read ldap directory...
I am sorry I got digressed but hope my point is clear at this point. I am not sure the way I handled this situation is right or wrong. I'd appreciate experienced engineers would clarify the way I handled the matter is acceptable in mockito way or not. If not, then plz advise me best way to handle it.
With Mockito,
a mock is an implementation of a wrapper class.
The mock object "wraps" the target of the mock
(the service in your example)
and allows you to define functionality of each method.
There are two mocked functionality options with Mockito;
call the wrapped method and don't call the wrapped method.
I don't know when it would make sense to call the wrapped method,
so I always use don't call the wrapped method.
After you create the mock,
use the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) method to mock functionality.
Edit: some more info.
I will assume that you are using junit v4.
The details of this will differ based on the the junit major release number,
but the actual work will be the same.
Use annotations to define your Mock objects (#Mock),
except in a few special cases.
This will create mocks of non-final classes,
abstract classes,
and interfaces.
Create a "before-test" method using the #Before annotation;
I traditionally name this method preTestSetup,
but the actual name does not matter.
Call MockitoAnnotations.initMocks(this) as the first line of code
in the "before-test" method.
This will find the #Mock annotations and instantiate a mock for each.
Use the ReflectionTestUtils.setField method to inject the mocks into your object (assuming that you don't have setter methods,
which I traditionally don't like).
Define the mocked functionality of each method using the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) technique.
Here is some example code
(caveat:
this should be fully functional,
but I did not compile it):
public interface MyService
{
String blammy(SomeParameter parameter);
}
public class UsesMyService
{
#Autowired
private MyService myService;
public String kapow(final SomeParameter parameter)
{
return myService.blammy(parameter);
}
}
public class UnitTestUsesMyService
{
private UsesMyService classToTest;
#Mock
private MyService mockMyService;
#Mock
private SomeParameter mockSomeParameter;
#Before
public void preTestSetup()
{
MockitoAnnotations.initMocks(this);
classToTest = new UsesMyService();
doReturn("Blam").when(mockMyService).blammy(mockSomeParameter);
ReflectionTestUtils.setField(
classToTest,
"myService",
mockMyService);
}
#Test
public void kapow_allGood_success()
{
final String actualResult;
actualResult = classToTest.kapow(mockSomeParameter);
assertNotNull(actualResult); // Not strictly necessary.
assertEquals(
"Blam",
actualResult);
}
}

Using PowerMockito.whenNew() is not getting mocked and original method is called

I have a code somewhat like this below:
Class A {
public boolean myMethod(someargs) {
MyQueryClass query = new MyQueryClass();
Long id = query.getNextId();
// some more code
}
}
Class MyQueryClass {
....
public Long getNextId() {
//lot of DB code, execute some DB query
return id;
}
}
Now I'am writing a test for A.myMethod(someargs). I want to skip the real method query.getNextId() and instead return a stub value. Basically, I want to mock MyQueryClass.
So in my test case, I have used:
MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);
boolean b = A.getInstance().myMethod(args);
//asserts
I used #RunWith(PowerMockRunner.class) and #PrepareForTest({MyQueryClass.class}) in the beginning of my test class.
But when I debug the test, it is still calling the real method getNextId() of the MyQueryClass class.
What am I missing here? Can anyone help as I am new to Mockito and PowerMockito.
You need to put the class where the constructor is called into the #PrepareForTest annotation instead of the class which is being constructed - see Mock construction of new objects.
In your case:
✗ #PrepareForTest(MyQueryClass.class)
✓ #PrepareForTest(A.class)
More general:
✗ #PrepareForTest(NewInstanceClass.class)
✓ #PrepareForTest(ClassThatCreatesTheNewInstance.class)
As #TrueDub mentioned in his accepted reply, you need to add the class where the constructor is called to the #PrepareForTest.
However, if you do this, coverage for that class as reported by eclemma and Sonar will be zero for that class
Powermockito wiki
We are going to replace Javassist with ByteBuddy (#727) and it should
help to resolve this old issue. But right now there is NO WAY TO USE
PowerMock with JaCoCo On-the-fly instrumentation. And no workaround to
get code coverage in IDE.
So the solution here would be to refactor the actual code to use a static factory that would return an instance of that class and then statically mock it.
Perhaps you can simply use
Mockito.doReturn(value).when(xxx)

Mock System class to get system properties

I have a folder path set in system variable through JVM arguments in Eclipse and I am trying to access it in my class as:
System.getProperty("my_files_path").
While writing junit test method for this class, I tried mocking this call as test classes do not consider JVM arguments. I have used PowerMockito to mock static System class and tried returning some path when System.getProperpty is being called.
Had #RunWith(PowerMockRunner.class) and #PrepareForTest(System.class) annotations at class level. However, System class is not getting mocked as a result I always get null result.
Any help is appreciated.
Thanks Satish. This works except with a small modification. I wrote PrepareForTest(PathFinder.class), preparing the class I am testing for test cases instead of System.class
Also, as mock works only once, I called my method right after mocking.
My code just for reference:
#RunWith(PowerMockRunner.class)
#PrepareForTest(PathInformation.class)
public class PathInformationTest {
private PathFinder pathFinder = new PathFinder();
#Test
public void testValidHTMLFilePath() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("my_files_path")).thenReturn("abc");
assertEquals("abc",pathFinder.getHtmlFolderPath());
}
}
There are certain classes PowerMock can't mock in the usual way. See here:
https://code.google.com/p/powermock/wiki/MockSystem
This, however, may still not work. In order of "good design" preference, you can fall back to these:
Refactor your code! Using a System property for passing a file path around is probably not the best way. Why not use a properties file loaded into a Properties object? Why not use getters/setters for the components that need to know this path? There are many better ways to do this.
The only reason I could think of not to do this is you're trying to wrap a test harness around code you "can't" modify.
Use #Before and #After methods to set the System property to some known value for the test(s). You could even make it part of the #Test method itself. This will be FAR easier than attempting to mock through PowerMock. Just call System.setProperty("my_files_path","fake_path");
System class is declared as final and cannot be mocked by libraries such as PowerMock. Several answers posted here are incorrect. If you are using Apache System Utils you can use getEnvironmentVariable method instead of calling System.getenv directly. SystemUtils can be mocked since it is not declared as final.
Set the system property in your test and ensure that it is restored after the test by using the rule RestoreSystemProperties of the library System Rules.
public class PathInformationTest {
private PathFinder pathFinder = new PathFinder();
#Rule
public TestRule restoreSystemProperties = new RestoreSystemProperties();
#Test
public void testValidHTMLFilePath() {
System.setProperty("my_files_path", "abc");
assertEquals("abc",pathFinder.getHtmlFolderPath());
}
}
The System.setter or getter method should be put in a user defined method and that method can be mocked to return the desired property in unit test.
public String getSysEnv(){
return System.getEnv("thisprp");
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(System.class)
public class MySuperClassTest {
#Test
public void test(){
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("java.home")).thenReturn("abc");
System.out.println(System.getProperty("java.home"));
}
}
Sailaja add System.class because as per the power mock guidelines for static,private mocking you should add the class in prepare for test.
#PrepareForTest({PathInformation.class,System.class})
Hope this helps.let me know if it doesn't work

Categories