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);
}
Related
My question is about testing a class that implements many interfaces. For example, I have this class:
public class ServiceControllerImpl extends ServiceController implements IDataChanged, IEventChanged {
}
Now there are two ways for testing. The first is testing directly on the concrete class. That means the object type is the concrete class rather than the interface.
public class ServiceControllerImplTest {
ServiceControllerImpl instance;
#Before
public void setUp() {
instance = new ServiceControllerImpl();
// you can bring this instance anywhere
}
}
The second way is testing on the interface only. We must typecast this object to all interfaces it implements.
public class ServiceControllerImplTest {
ServiceController instance; // use interface here
IDataChanged dataChangeListener;
#Before
public void setUp() {
instance = new ServiceControllerImpl();
dataChangeListener = (IDataChanged) instance;
// instance and dataChangeListener "look like" two different object.
}
}
I prefer the second solution because maybe in future we can change the interface it implements to other objects, so using the concrete class might lead to failing tests in the future. I don't know the best practice for this problem.
Thanks :)
I prefer second solution because in reality, maybe in future we can change the interface it implements to other objects, so force using concreted class maybe leads to fail test in the future.
I guess it will lead to failed tests anyway, because you usually test that assertions are true or false. The question is: Do that tests apply to any IDataChanged or do these assertions only apply to the ServiceControllerImpl?
If the assertions only apply to the ServiceControllerImpl it doesn't matter if you use an IDataChanged instead of an ServiceControllerImpl, because you must edit the test when you use another IDataChanged object - different assertions. The test will fail if you use another object.
The way you setup unit tests Itself gives you an answer. A unit test usually tests one class in isolation. This means that you mock the environment. But mocking the environment means that you know the dependencies of the class you test and this are implementation details. So your test is written on an implemtation basis rather than only the interface.
It's possible to write tests that only test an abstract api - like an interface. But this usually means that your tests are abstract too. E.g.
public abstract class SetTest {
#Test
public void addAlreadyExistentObject(){
Set<String> setUnderTest = createSetUnderTest();
Assert.assertTrue(setUnderTest.isEmpty());
boolean setChanged = setUnderTest.add("Hello");
Assert.assertTrue(setChanged);
setChanged = setUnderTest.add("Hello");
Assert.assertFalse(setChanged);
Assert.assertEquals(setUnderTest.size(), 1);
}
protected abstract Set<String> createSetUnderTest();
}
You can then extend these abstract tests to test the api for concrete classes. E.g.
public class HashSetTest extends SetTest {
#Override
protected Set<String> createSetUnderTest() {
return new HashSet<String>();
}
}
In this case you can replace the implementation and the test must remain green.
But here is another example of an abstract api when replacing the object under test does not really make sense.
What about writing a test for all Runnables?
public class RunnableTest {
#Test
public void run(){
Runnable runnable = ...;
// What to test here?
// run is invoked without throwing any runtime exceptions?
runnable.run();
}
}
As you can see it does not make sense in some cases to write tests in a way so that you can easily replace the object under test.
If an api like the Set api defines a concrete state handling you can write abstract tests that test this.
JayC667 already correctly answered that it's best to refer to a class through its supertype(s) in tests of methods defined by those types. But I'd change the way you did that a bit to avoid casting:
public class ServiceControllerImplTest {
ServiceController controller;
IDataChanged dataChangeListener;
#Before
public void setUp() {
instance = new ServiceControllerImpl();
controller = instance;
dataChangeListener = instance;
}
}
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);
}
}
I have simple test case:
#Test
public void test() throws Exception{
TableElement table = mock(TableElement.class);
table.insertRow(0);
}
Where TableElement is GWT class with method insertRow defined as:
public final native TableRowElement insertRow(int index);
When I launch test I'm getting:
java.lang.UnsatisfiedLinkError: com.google.gwt.dom.client.TableElement.insertRow(I)Lcom/google/gwt/dom/client/TableRowElement;
at com.google.gwt.dom.client.TableElement.insertRow(Native Method)
Which as I believe is related with insertRow method being native. Is there any way or workaround to mock such methods with Mockito?
Mockito itself doesn't seem to be able to mock native methods according to this Google Group thread. However you do have two options:
Wrap the TableElement class in an interface and mock that interface to properly test that your SUT calls the wrapped insertRow(...) method. The drawback is the extra interface that you need to add (when GWT project should've done this in their own API) and the overhead to use it. The code for the interface and the concrete implementation would look like this:
// the mockable interface
public interface ITableElementWrapper {
public void insertRow(int index);
}
// the concrete implementation that you'll be using
public class TableElementWrapper implements ITableElementWrapper {
TableElement wrapped;
public TableElementWrapper(TableElement te) {
this.wrapped = te;
}
public void insertRow(int index) {
wrapped.insertRow(index);
}
}
// the factory that your SUT should be injected with and be
// using to wrap the table element with
public interface IGwtWrapperFactory {
public ITableElementWrapper wrap(TableElement te);
}
public class GwtWrapperFactory implements IGwtWrapperFactory {
public ITableElementWrapper wrap(TableElement te) {
return new TableElementWrapper(te);
}
}
Use Powermock and it's Mockito API extension called PowerMockito to mock the native method. The drawback is that you have another dependency to load into your test project (I'm aware this may be a problem with some organizations where a 3rd party library has to be audited first in order to be used).
Personally I'd go with option 2, as GWT project is not likely to wrap their own classes in interfaces (and it is more likely they have more native methods that needs to be mocked) and doing it for yourself to only wrap a native method call is just waste of your time.
In case anybody else stumbles about this: In the meantime (in May 2013) GwtMockito turned up, which solves this problem without PowerMock's overhead.
Try this
#RunWith(GwtMockitoTestRunner.class)
public class MyTest {
#Test
public void test() throws Exception{
TableElement table = mock(TableElement.class);
table.insertRow(0);
}
}
I'm new to using Mockito and am trying to understand a way to make a unit test of a class that relies on injected dependencies. What I want to do is to create mock objects of the dependencies and make the class that I am testing use those instead of the regular injected dependencies that would be injected by Spring. I have been reading tutorials but am a bit confused on how to do this.
I have one the class I want to test like this:
package org.rd.server.beans;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean1 {
#Autowired
private SubBean1 subBean1;
private String helloString;
public String testReturn () {
subBean1.setSomething("its working");
String something = subBean1.getSomething();
helloString = "Hello...... " + something;
return helloString;
}
Then I have the class that I want to use as a mock object (rather than the regular SubBean1 class, like below:
package org.rd.server.beans.mock;
public class SubBean1Mock {
private String something;
public String getSomething() {
return something;
}
public void setSomething(String something) {
this.something = something;
}
}
}
I just want to try running a simple test like this:
package test.rd.beans;
import org.rd.server.beans.TestBean1;
import junit.framework.*;
public class TestBean1Test extends TestCase
{
private TestBean1 testBean1;
public TestBean1Test(String name)
{
super(name);
}
public void setUp()
{
testBean1 = new TestBean1();
// Somehow inject the mock dependency SubBean1Mock ???
}
public void test1() {
assertEquals(testBean1.testReturn(),"working");
}
}
I figure there must be some fairly simple way to do this but I can't seem to understand the tutorials as I don't have the context yet to understand everything they are doing / explaining. If anyone could shed some light on this I would appreciate it.
If you're using Mockito you create mocks by calling Mockito's static mock method. You can then just pass in the mock to the class you're trying to test. Your setup method would look something like this:
testBean1 = new TestBean1();
SubBean1 subBeanMock = mock(SubBean1.class);
testBean1.setSubBean(subBeanMock);
You can then add the appropriate behavior to your mock objects for whatever you're trying to test with Mockito's static when method, for example:
when(subBeanMock.getSomething()).thenReturn("its working");
In Mockito you aren't really going to create new "mock" implementations, but rather you are going to mock out the methods on the interface of the injected dependency by telling Mockito what to return when the method is called.
I wrote a test of a Spring MVC Controller using Mockito and treated it just like any other java class. I was able to mock out the various other Spring beans I had and inject those using Spring's ReflectionTestUtils to pass in the Mockito based values. I wrote about it in my blog back in February. It has the full source for the test class and most of the source from the controller, so it's probably too long to put the contents here.
http://digitaljoel.nerd-herders.com/2011/02/05/mock-testing-spring-mvc-controller/
I stumbled on this thread while trying to set up some mocks for a slightly more complicated situation and figured I'd share my results for posterity.
My situation was similar in the fact that I needed to mock dependencies, but I also wanted to mock some of the methods on the class I was testing. This was the solution:
#MockBean
DependentService mockDependentService
ControllerToTest controllerToTest
#BeforeEach
public void setup() {
mockDependentService = mock(DependentService.class);
controllerToTest = mock(ControllerToTest.class);
ReflectionTestUtils.setField(controllerToTest, "dependantService", mockDependentService);
}
#Test
void test() {
//set up test and other mocks
//be sure to implement the below code that will call the real method that you are wanting to test
when(controllerToTest.methodToTest()).thenCallRealMethod();
//assertions
}
Note that "dependantService" needs to match whatever you have named the instance of the service on your controller. If that doesn't match the reflection will not find it and inject the mock for you.
This approach allows all the methods on the controller to be mocked by default, then you can specifically call out which method you want to use the real one. Then use the reflection to set any dependencies needed with the respective mock objects.
Hope this helps someone down the road as it stumped me for a while.
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.