Would it be valid to assert on mockito spyed object? - junit

I am spying an object like:
#Spy
#InjectMocks
private final A a= new A()
and in test case I am asserting on properties of A object.
As spying an object means calling real methods, would it be right to asserting on properties of spyed objects?

Technically it will work, but I recommend against it, it's usually a bad idea (even an anti-pattern) to mock value object.
If the test is to verify properties have changed to specific values then this object is the tested object and as such there would be no reason for it to be a spy.
If creating a simple value object is too difficult with the current API, then there's a usability problem in the tested code, refactoring or utility is needed to create valid instances easily.
Only in some very specific edge cases one would need the combination of a #Spy and #InjectMocks. Most the time it is not needed, and such tests show a design issue in the tested code.
Instead just create a real object, inject mocks if needed and assert properties directly on the tested object. A good spy usage would be verifying that there was interactions between two collaborating objects only.

Related

Grails JSON marhsaling using introspection causes severe bottleneck on Classloader.loadClass()

I am using Grails 2.2.4 and have a controller endpoint which converts a domain object list to JSON. Under load (as little as 5 concurrent requests) the marshaling performance is very poor. Taking thread dumps the threads are blocked on:
java.lang.ClassLoader.loadClass(ClassLoader.java:291)
There is a single marhsaler registered to marshal all domain objects using reflection and introspection. Realizing that reflection and introspection is slower than direct method calls, I am still seeing unexpected behavior in that the class loader is caller every time and in turn blocking occurs. An example stacktrace is as follows:
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.ClassLoader.loadClass(ClassLoader.java:291)
- waiting to lock <785e31830> (a org.grails.plugins.tomcat.ParentDelegatingClassLoader)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.beans.Introspector.instantiate(Introspector.java:1470)
at java.beans.Introspector.findExplicitBeanInfo(Introspector.java:431)
at java.beans.Introspector.<init>(Introspector.java:380)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at java.beans.Introspector.getBeanInfo(Introspector.java:230)
at java.beans.Introspector.<init>(Introspector.java:389)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at java.beans.Introspector.getBeanInfo(Introspector.java:230)
at java.beans.Introspector.<init>(Introspector.java:389)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at java.beans.Introspector.getBeanInfo(Introspector.java:230)
at java.beans.Introspector.<init>(Introspector.java:389)
at java.beans.Introspector.getBeanInfo(Introspector.java:167)
at org.springframework.beans.CachedIntrospectionResults.<init>(CachedIntrospectionResults.java:217)
at org.springframework.beans.CachedIntrospectionResults.forClass(CachedIntrospectionResults.java:149)
at org.springframework.beans.BeanWrapperImpl.getCachedIntrospectionResults(BeanWrapperImpl.java:324)
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:727)
at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:721)
at org.springframework.beans.PropertyAccessor$getPropertyValue.call(Unknown Source)
at com.ngs.id.RestDomainClassMarshaller.extractValue(RestDomainClassMarshaller.groovy:203)
...
...
A simple benchmark loading the same endpoint with the same parameters results in the loadClass call.
I was under the impression the classes would be at least cached by the class loader and not loaded on every method call to get the property to be marshaled.
The code to retrieve the property value is as follows:
BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(domainObject);
return beanWrapper.getPropertyValue(property.getName());
Is there a configuration setting that is needed to ensure the classes are only loaded once? or perhaps a different way to get the property that doesn't result in class loading every time? Or perhaps a more performant way to achieve this?
Writing a custom marshaler per domain class would avoid the reflection and introspection but is going to be a lot of repeat code.
Appreciate any input.
So after much digging this is what I found out.
Using the BeanUtils.getPropertyDescriptors and getValue will always try and find a BeanInfo class describing the bean using the class loader. In this case we don't provide BeanInfo classes for our grails domain classes so this call is redundant. I found some information where you can provide a custom BeanInfoFactory to bypass this and exclude your packages but I couldn't find how to configure it with Grails.
Also searching the springframework documentation there is a configuration option you can pass Introspector.IGNORE_ALL_BEANINFO that will tell CachedIntorspectionResults to never look up the bean classes. However this was not available in version 3.1.4 of springframework which was current for grails 2.2.4. The newer versions do appear to have this option.
So, if using BeanUtils you can't by pass this initial lookup on the class loader. However subsequent loaders should be cached by CachedIntrospectionResults. Unfortunately this doesn't happen in our scenario. There looks to be a bug in the test to see if the lookup is cacheable. See more info on this below.
The fix was ultimately to fall back to use pure reflection. Rather than use:
beanWrapper.getPropertyValue(property.getName());
To use:
PropertyDescription pd = BeanUtils.getPropertyDescriptor(domainObject.getClass(), property.getName())
pd.readMethod.invoke(domainObject)
Where the pd is cached.
After fixing this the profiler still showed a lack of caching on CachedIntorspectionResults for the out of the box grails marshaller. This was due to the bad caching implementation in CachedIntrospectionResults. The work around for this was to add the correct class loader to the acceptedClassLoaders in the CachedIntrospectionResults.
public class EnhanceCachedIntrospectionResultsAcceptedClassLoadersListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
CachedIntrospectionResults.acceptClassLoader(Thread.currentThread().getContextClassLoader().getParent());
}
public void contextDestroyed(ServletContextEvent event) {
CachedIntrospectionResults.clearClassLoader(Thread.currentThread().getContextClassLoader().getParent());
Introspector.flushCaches();
}
}
Note that it was required to add the parent to the accepted class loader list rather than the current class loader. Not sure if this is specific to grails or not but this fixed the issue. I'm not sure if there may be a side effect to this fix.
In summary we went from 10 requests/sec in the original setup to 120 requests/sec after using direct reflection and fixing the CachedIntrospectionResults cache.
However the real eye opened was that if we use a 1-1 marshaller per domain class we were seeing another x2 improvement in performance over the generic marshaller where we test objects for whether they're instances of class etc. We're saving a lot of code with the generic marshaller but there's a lot more work to do to get comparable performance to writing a 1-1 marshaller.
Hopefully this will be useful to someone else who runs into this ...

ILSpy (a.k.a. .NET Reflector) shows a method as just calling itself, why?

When passing anonymous types to an HtmlHelper method like TextBox, you'll get binding errors (because anonymous type members have internal access only), unless you use a RouteDataDictionary to extract the members.
When I saw that the (HtmlHelper extension) InputExtensions.TextBox method accepted anonymous types, I knew it had to be doing some conversion internally or it would fail with the same error.
Sure enough, it calls HtmlHelper.AnonymousObjectToHtmlAttributes method, whose documentation tries to play down the issue by not mentioning it, instead suggesting it's just replacing underscores with dashes to ensure valid attribute names are used. Sure. Anyway...
I wanted to see exactly what that conversion looks like, but when I inspect HtmlHelper's static method with that name in ILSpy, the method appears to just call itself. What is going on here?
public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes)
{
return HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
}
The method AnonymousObjectToHtmlAttributes from System.Web.MVC.HtmlHelper is calling a method with the same name but from System.Web.WebPages.Html.HtmlHelper.
The ILSpy is not explicitly about that. I needed to hover the class to show from where it was coming:
I asked a similar question that was anwered here.

SharedObject and Dictionary problems in Flash Builder

I'm usin Flash Builder to create some actionscript code that uses SharedObjects.
First question: how can I delete my local SharedObject in Flash Builder? I am debugging my program and the SharedObject sems to persist between runs. I want to start fresh and clean with no SharedObject storing my data. How do I get rid of it?
Also, in my SharedObject, I used mySharedObject.data["mykey"] to store a Dictionary. This Dictionary will have String keys and values of MyCustomClass. The problem is that when I later try to loop over the values of this Dictionary, I get error #1034 cannot convert object to type MyCustomClass. It seems like I can put an item of type MyCustomClass into this dictionary, but I can't get the item back out as anything other than an object.
Any idea what is going wrong?
Those are essentially two questions, so should have been asked as two questions. Anyway, I'd answer them here but still prefer that you break them up in two parts (possibly leave a link to the other one here for reference sake):
Local shared object, are useful exactly for persistence across runs. And then there's SharedObject.clear() to clear the state as required.
For you second issue, Shared Object's serialize your object into AMF, so that it can be written to disk or sent over network using RTMP. Now, your custom class can't really be serialized in AMF. What actually happens is that the public properties (and dynamic ones, if the class is declared dynamic) are serialized into the structure. So, the public data is stored... but it's essentially a general Object.
To work around that, you can have a public static readFrom(object:Object):MyCustomClass type function, which would read the properties from the passed object to construct a new MyCustomClass representing that information.
There are ways to register your class with the player to be stored in SharedObject (see here)... but you need to make sure that the code that de-serializes that data is aware of the class as well.
To make a class available for conversion, in your global initialization use registerClassAlias() call with MyCustomClass and its fully qualified name as parameters. The manual. Say your custom class is foo.bar.TheClass, you write:
registerClassAlias('foo.bar.TheClass',foo.bar.TheClass);
In order to drop old SO use delete call against so.data["mykey"] and do so.flush(). Edit: SharedObject.clear() is way better.
1/ Being persistent is one of the particularity of a SharedObject. To cleanup all its content, you need to call the clear method.
var shareObject:SharedObject = SharedObject.getLocal('justatest');
shareObject.data.test = 'test';
trace(shareObject.data.test)
shareObject.clear();
trace(shareObject.data.test)
output
test
undefined
2/ To store complex data types in SO, you need to use flash.net.registerClassAlias (example here)

Looking for way to replace many "when...thenReturn" statements in test method

I'm writing a JUnit test on a method that is interacting primarily with classes in org.apache.poi.hssf.usermodel (like HSSFWorkbook, HSSFFont and HSSFCellStyle).
The method ultimately builds up and returns an HSSFWorkbook object.
In order to build up the HSSFWorkbook object, methods like workbook.createFont() and workbook.createCellStyle() are invoked.
I currently mock out the objects like this in the setup class of my unit test
workbook = mock(HSSFWorkbook.class);
font = mock(HSSFFont.class);
cellStyle = mock(HSSFCellStyle.class);
Then, in my test method, I invoke the following to avoid NPEs
when(workbook.createFont()).thenReturn(font);
when(workbook.createCellStyle()).thenReturn(cellStyle);
I'm discovering I'll have to do many more of those in order to avoid the NPEs and I'm wondering if there's a way that I can avoid writing all of those "when...thenReturn" statements.
one of the rules of Mocking is: Never mock types you don't own. Another rule is a stubbed call on a mock, shouldn't return another mock.
The reason is in front of you :).
If your class only deals with creating the HSSFWorkbook, then treat the tests as integration tests and use the real library. If your class does something else too, then move all the other stuff to other classes (this is to follow the single responsibility principle)

Mock methods not directly called in unit test with JMock

I have a method under test. Within its call stack, it calls a DAO which intern uses JDBC to chat with the DB. I am not really interested in knowing what will happen at the JDBC layer; I already have tests for that, and they work wonderfully.
I am trying to mock, using JMock, the DAO layer, so I can focus on the details this method under test. Here is a basic representation of what I have.
#Test
public void myTest()
{
context.checking(new Expectations() {
{
allowing(myDAO).getSet(with(any(Integer.class)));
will(returnValue(new HashSet<String>()));
}
});
// Used only to show the mock is working but not really part of this test.
// These asserts pass.
Set<String> temp = myDAO.getSet(Integer.valueOf(12));
Assert.assertNotNull(temp);
Assert.assertTrue(temp.isEmpty());
MyTestObject underTest = new MyTestObject();
// Deep in this call MyDAO is initialized and getSet() is called.
// The mock is failing to return the Set as desired. getSet() is run as
// normal and throws a NPE since JDBC is not (intentionally) setup. I want
// getSet() to just return an empty set at this layer.
underTest.thisTestMethod();
...
// Other assertions that would be helpful for this test if mocking
// was working.
}
It, from what I have learned creating this test, that I cannot mock indirect objects using JMock. OR I am not seeing a key point. I'm hoping for the second half to be true.
Thoughts and thank you.
From the snippet, I'm guessing that MyTestObject uses reflection, or a static method or field to get hold of the DAO, since it has no constructor parameters. JMock does not do replacement of objects by type (and any moment now, there'll be a bunch of people recommending other frameworks that do).
This is on purpose. A goal of JMock is to highlight object design weaknesses, by requiring clean dependencies and focussed behaviour. I find that burying DAO/JDBC access in the domain objects eventually gets me into trouble. It means that the domain objects have secret dependencies that make them harder to understand and change. I prefer to make those relationships explicit in the code.
So you have to get the mocked object somehow into the target code. If you can't or don't want to do that, then you'll have to use another framework.
P.S. One point of style, you can simplify this test a little:
context.checking(new Expectations() {{
allowing(myDAO).getSet(12); will(returnValue(new HashSet<String>()));
}});
within a test, you should really know what values to expect and feed that into the expectation. That makes it easier to see the flow of values between the objects.