I would like to test that my call of Window.open(String) is with the correct URL (to download a file).
Is there any better way of doing it, besides using a partial mock, like this?
MySUT sut = Mockito.spy(new MySUT());
String expectedURL = "http://www.example.com";
doNothing().when(sut).openWindow(expectedURL);
sut.doSomethingThatOpensURL();
verify(sut).openWindow(expectedURL);
Where openWindow(String) is as simple as possible in MySUT:
void openWindow(String url) {
Window.open(url);
}
Does GwtMockito give you something to test methods that execute native javascript like Window.open(String)?
I suppose there is no ability to verify it using GwtMockito.
But I believe it's possible using PowerMock and EasyMock.
This mocking frameworks provide great flexibility to test static methods and 3rd party classes.
I've just created a simple example how you can test Window.open().
In my test case I'm just checking Window.alert(), for example.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Window.class)
#SuppressStaticInitializationFor("com.google.gwt.user.client.Window")
public class SimpleTester {
/** Simple class for test. */
private class TestClass {
public void open(String url) {
Window.alert(url);
}
}
#Test
public void test() {
PowerMock.mockStatic(Window.class);
TestClass obj = new TestClass();
Window.alert("test");
EasyMock.expectLastCall();
PowerMock.replay(Window.class);
obj.open("test");
PowerMock.verify(Window.class);
}
}
Related
I have the following method to write a test for:
public QuiltResponse create(QuiltRequest quiltRequest, MultipartFile image) throws IOException {
String fileNameUuid = UUID.randomUUID().toString();
saveImage(image, fileNameUuid);
Quilt newQuilt = quiltFactory.create(quiltRequest, fileNameUuid);
return new QuiltResponse(quiltRepository.save((newQuilt)), HttpStatus.OK);
}
I understand why my test won't work: I can't mix up the mocks and the anyString()s. I really want to replace anyString() with the fileNameUuid as generated within the create() method I am trying to test. Is this possible? Thanks!
#Test
void shouldPassToConfirmCreateCallsCorrectUnderlyingMethods() throws IOException {
QuiltRequest mockQuiltRequest = mock(QuiltRequest.class);
MultipartFile mockImage = mock(MultipartFile.class);
QuiltFactory mockQuiltFactory = mock(QuiltFactory.class);
DefaultQuiltService mockQuiltService = mock(DefaultQuiltService.class);
mockQuiltService.create(mockQuiltRequest, mockImage);
verify(mockQuiltService).saveImage(mockImage, anyString());
verify(mockQuiltFactory).create(mockQuiltRequest, anyString());
}
You need use Powermock
import static org.powermock.api.mockito.PowerMockito.mockStatic;
#PrepareForTest({UUID.class})
#RunWith(PowerMockRunner.class)
public void yourTestMethod(){
mockStatic(UUID.class);
when(UUID.randomUUID()).thenReturn("your-UUID");
}
You can
Use the Powermock library. https://github.com/powermock/powermock
And that one is better as I think (powermock is slow)
Create a class which will be called in your service, for example UidProvider, create an instance method in it, inject it to he testable code, mock it with regular mockito, that will make your test way faster, and the code more SOLID.
Your production code will look like that:
public QuiltResponse create(QuiltRequest quiltRequest, MultipartFile image) throws IOException {
String fileNameUuid = uidProvider.getUid();
saveImage(image, fileNameUuid);
Quilt newQuilt = quiltFactory.create(quiltRequest, fileNameUuid);
return new QuiltResponse(quiltRepository.save((newQuilt)), HttpStatus.OK);
}
You can then easily mock the behaviour of your uid generation logic, and not add additional dependencies, and not make your tests slow because of the static mocking.
I have a block of code for which I need to test .Lets say
Class MainClass{
public void startProcess() {
----Some Logic to generate fileName;
uploadFile(fileName);
}
private static void uploadFile(String key) {
fileUpload();
deleteFile();
}
}
I want to write a JUNIT test which will call startProcess but either skip the uploadFile line or just ignore any lines present in uploadFile method .
I tried to use powerMock but it doesnt work . Below is my code
#RunWith(PowerMockRunner.class)
#PrepareForTest(MainClass.class)
public class MainClassTest {
#Test
public void teststartProcess() throws Exception {
processor=PowerMock.createPartialMock(MainClass.class,"uploadFile");
PowerMock.expectPrivate(processor , "uploadFile", "xyz").andAnswer(
new IAnswer<Void>() {
#Override
public Void answer() throws Throwable {
System.out.println("Invoked!");
return null;
}
}).atLeastOnce();
}
}
But it does't override the method uploadFile to just print invoked . It calls fileUpload and deleteFile instead of just skipping the lines and print invoke .
My basic goal is to mock the method uploadFile to just print
private void uploadFile(String key) {
System.out.println("Invoked");
}
I know it's possible using Mockito but we can use either PowerMock or EasyMock .
Instead of trying to go the way with over complicated tests you should consider to refactor your code so that it is testable. From what you provided I would move the file functionality to another class.
something like this:
public class MainClass {
private final FileUploader fileUploader;
public MainClass(FileUploader fileUploader) {
this.fileUploader= fileUploader;
}
public void startProcess() {
fileUploader.uploadFile(fileName);
}
}
With this refactoring you gain the possibility to use plain mocking for the test:
String fileName = "foo";
FileUploader fileUploader = mock(FileUploader.class);
MainClass classUnderTest = new MainClass(fileUploader);
classUnderTest.startProcess();
verify(fileUploader, times(1)).uploadFile(fileName);
An additional benefit is that testing the fileUploader becomes also easy. As you can see I also got rid of all the complicated Partial mocking and private testing.
You have to change the mock object to replay mode before calling the method under test and you have to tell Powermock to work on a static method:
mockStaticStrict(MainClass.class,method(MainClass.class, "uploadFile"));
PowerMock.replay(processor);
processor.startProcess();
See Mocking private methods for further information on this.
I highly suggest to refactor this code and make it testable.
Trying to use Mockito's spy function for my JUnit test. I originally had a Class:
public class App1 {
public String method1() {
sayHello();
}
public sayHello() {
Systems.out.println("Hello");
}
}
Everything in my test class was working correctly with mockito spy on above class:
#Test(expected = IOException.class)
public void testMethod1Failure(){
App1 a1 = spy(App1);
doThrow(IOException.class).when(a1).sayHello();
a1.method1();
}
But after that i had to switch things around and take sayHello() method into another class to be used as static method:
public class App1 {
public String method1() {
App2.sayHello();
}
}
public class App2 {
public static void sayHello() {
Systems.out.println("Hello");
}
}
After this change, my original JUnit testcase is broken and i am unsure how i can use Mockito spy to start App1 that calls the external App2 static method... does anyone know how i can do it? Thanks in advance
Mockito does not support mocking static code. Here are some ways to handle it:
Use PowerMockito or similar framework as suggested here: Mocking static methods with Mockito.
Refactor your code converting static method back to an instance method. As you've found static methods are not easy to Unit test.
If it's inexpensive to execute actual static method in question then just call it.
Is it possible to mock a class object using Mockito and/or PowerMockito?
Something like:
Class<Runnable> mockRunnableClass = mock(Class<Runnable>.class);
An alternative to mocking Class might be to use a Factory instead. I know you are concerned about refactoring, but this could be done without changing the public API of the class. You haven't provided much code to understand the class you are trying to test, but here's an example of refactoring without changing the API. It's a trivial class, but it might give you an idea.
public class Instantiator {
public Runnable getNewInstance(Class<Runnable> runnableClass) throws Exception {
return runnableClass.newInstance();
}
}
Of course, the easiest thing to do to test this trivial class would be to use a genuine Runnable class, but if you tried to mock the Class, you would run into the problems you're having. So, you could refactor it thus:
public class PassThruFactory {
public Object newInstance(Class<?> clazz) throws Exception {
return clazz.newInstance();
}
}
public class Instantiator {
private PassThruFactory factory = new PassThruFactory();
public Runnable getNewInstance(Class<Runnable> runnableClass) throws Exception {
return (Runnable)factory.newInstance(runnableClass);
}
}
Now Instantiator does exactly the (trivially simple) thing it was doing before with the same public API and no need for any client of the class to do any special injecting of their own. However, if you wanted to mock the factory class and inject it, that's very easy to do.
why not using an agent if you can't refactor the code there isn't many options, as #jherics mentionned, java system classes are loaded by the bootstrap classloader and powermock can't redefine their bytecode.
However Powermock now coms with an agent, that will allow system classes mock. Check here for complete explanation.
The main idea is to modify your java command and add :
-javaagent: path/to/powermock-module-javaagent-1.4.12.jar
The basic thing this agent is doing is to definalize classes, to allow future mocking in a specific test, that's why you'll need to use specific types to communicate with the agent, for example with JUnit :
#Rule PowerMockRule rule = new PowerMockRule(); // found in the junit4 rule agent jar
TestNG is also supported. Just check the wiki page for more information.
Hope that helps.
First, as stated in the comments, you would need to do:
Class<Runnable> mockRunnableaClass = (Class<Runnable>)mock(Class.class);
But that won't work in the usual way because of a limitation with PowerMock. You cannot simply mock classes in from java.lang, java.net, java.io or other system classes because they're loaded by Java's bootstrap classloader and cannot be byte-code manipulated by PowerMock's classloader. (See PowerMock FAQ #4.) As of PowerMock 1.2.5, you can work around this. If the class you wanted to test was this:
public class ClassToTest {
private Class<Runnable> runnableClass;
public void setRunnableClass(Class<Runnable> runnableClass) {
this.runnableClass = runnableClass;
}
public Runnable foo() {
return runnableClass.newInstance();
}
}
Then you would do this:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ClassToTest.class }) // Prepare the calling class for test
public class SystemClassUserTest {
#Test
public void testFoo() throws Exception {
Class<Runnable> mockClass = (Class<Runnable>) mock(Class.class);
Runnable mockRunnable = mock(Runnable.class);
ClassToTest objectUT = new ClassToTest();
objectUT.setRunnableClass(mockClass);
when(mockClass.newInstance()).thenReturn(mockRunnable);
assertThat(objectUT.foo(), is(sameInstance(mockRunnable);
}
}
How about this. creating a get method of the has a Object (MS) in class PCService and then mock it.
public class PCService implements PCServiceIf {
public MSIf getMS() {
return ms;
}
private MSIf ms = new MS();
public boolean isMovieAccessibleToMyLevel(String myLevel, String movieId) {
return getMS().getPCL(movieId);
}
}
#Test
public void testIsMovieAccessibleToMyLevelMock() {
msMock = mock(MS.class);
spy = spy(new PCService());
doReturn(msMock).when(spy).getMS();
when(msMock.getPCL(movieId)).thenReturn(value);
when(spy.getMS().getPCL(movieId)).thenReturn(value);
assertTrue(spy.isMovieAccessibleToMyLevel("PG", movieId) == true);
}
Let's say you have some 3rd-party library class that you want to extend, simply to add convenience methods to it (so you can call an inherited method with default parameters for example).
Using jUnit/jMock, is it possible to write an assertion / mock expection that tests that the correct inherited method is called?
For example, something like this:
class SomeClass extends SomeLibraryClass {
public String method(String code) {
return method(code, null, Locale.default());
}
}
How can I assert that method is being called?
You can make a further subclass inside your unit test that actually tells you:
public class MyTest {
boolean methodCalled = false;
#Test
public void testMySubclass(){
TestSomeClass testSomeClass = new TestSomeClass();
// Invoke method on testSomeclass ...
assertTrue( methodCalled);
}
class TestSomeClass extends SomeClass{
public String method(String code){
methodCalled = true;
}
}
}
Unit testing is more useful to verify the functionality of given methods, not to assert coverage. Unit tests that care more about what method got called know way more about the classes they are testing than they probably should, not to mention will be confusing to the reader.
Coverage tools like Cobertura or EMMA will tell you whether you properly covered your code.
It may indeed be better to only write integration tests in this case, but if you really want a unit test, you can have it just as easily as in any other case:
public class SomeClassTest
{
#Test
public void testMethod()
{
final String code = "test";
new Expectations()
{
SomeLibraryClass mock;
{
mock.method(code, null, (Locale) any);
}
};
new SomeClass().method(code);
}
}
This test uses the JMockit mocking API.
it's hard to tell without a more concrete example, but I'd guess that this ought to be an integration test--test the whole package together--rather than a unit test. Sometimes one can be too fine-grained with unit testing.