keeganwitt / gmock

Automatically exported from code.google.com/p/gmock
6 stars 2 forks source link

Mocking a method called setProperty() places an expectation on the property of an object being set #89

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Mock an object that has a setProperty(name, value) method
2. Place an expectation of a call to setProperty(name, value)
3. During play, exercise a call to setProperty(name, value)

What is the expected output? What do you see instead?

GMock expects that the property should be explicitly set instead of a call
to the setProperty(name,value) method:

junit.framework.AssertionFailedError: Unexpected property setter call

What version of the product are you using? On what operating system?

Using 0.8.0 on Ubuntu 9.04.

Please provide any additional information below.

I was asked to raise an issue based on this posting:
http://prystash.blogspot.com/2009/07/gmock-mocking-property-setting-via.html

The object I mocked had a setProperty() method that I wanted to verify. 
GMock was expecting the actual setting of the property.

The posting:
Below is a Java method I wanted to mock using GMock. The class under test
is validating an incoming message in a Mule container. The features and
properties passed into the set methods below are static in the class under
test, OrderValidationRouter.

    private void setSchemaValidationFeatures(SAXReader reader) throws
Exception {
        reader.setValidation(true);
        reader.setFeature(VALIDATION_SCHEMA, true);
        reader.setFeature(VALIDATION_SCHEMA_FULL_CHECKING, true);         

        reader.setProperty(SCHEMA_LANGUAGE, SCHEMA_LANGUAGE_VALUE);
        reader.setProperty(SCHEMA_SOURCE, getXsdAsStream());
    }

My first attempt at testing the method with GMock:

@WithGMock
class OrderValidationRouterTest {

    OrderValidationRouter router

    @Before
    void setUp() {
        router = new OrderValidationRouter()
    }

    @Test
    void testSettingSchemaValidationFeatures() {
        def readerMock = mock(SAXReader)
        def xsdStream = new ByteArrayInputStream()

        router.setXsdAsStream(xsdStream)

        readerMock.setValidation(true)
        readerMock.setFeature(
            OrderValidationRouter.VALIDATION_SCHEMA, true)
        readerMock.setFeature(
            OrderValidationRouter.VALIDATION_SCHEMA_FULL_CHECKING, true)
        readerMock.setProperty(OrderValidationRouter.SCHEMA_LANGUAGE,
            OrderValidationRouter.SCHEMA_LANGUAGE_VALUE)
        readerMock.setProperty(OrderValidationRouter.SCHEMA_SOURCE, xsdStream)

        play {
            router.setSchemaValidationFeatures(readerMock)
        }
    }
}

The test worked fine with the exception of the setProperty() expectations,
producing the following test failure:

junit.framework.AssertionFailedError: Unexpected property setter call 
'"http://java.sun.com/xml/jaxp/properties/schemaLanguage" =
"http://www.w3.org/2001/XMLSchema"'

Turns out I need to mock the actual setting of the property and not the
method call. There are several ways to do this, but I went with the first
thing that came to mind:

   def property = OrderValidationRouter.SCHEMA_LANGUAGE
   def value = OrderValidationRouter.SCHEMA_LANGUAGE_VALUE
   readerMock."$property".set(value)

   property = OrderValidationRouter.SCHEMA_SOURCE
   value = xsdStream
   readerMock."$property".set(value)

The property variable needs to be interpolated in a GString or else the
mock will be expecting for a property named property to be set.

Original issue reported on code.google.com by prysta...@gmail.com on 6 Sep 2009 at 3:20

GoogleCodeExporter commented 9 years ago
Thanks for your report

Original comment by JohnnyJianHY on 7 Sep 2009 at 1:05

GoogleCodeExporter commented 9 years ago

Original comment by JohnnyJianHY on 13 Sep 2009 at 3:01

GoogleCodeExporter commented 9 years ago
I have fixed this bug by changing the mocking process: not to force the mock 
objects to 
implement GroovyObject, as Groovy 1.6.x supports per-instance meta class for 
all 
objects. However, it is not so easy, and I have introduced two meta classes 
named 
GeneratedClassProxyMetaClass and GeneratedMockProxyMetaClass, one for the cglib 
generated classes and the other for their instances.

Original comment by JohnnyJianHY on 14 Sep 2009 at 3:14