[ 
https://issues.apache.org/jira/browse/TINKERPOP-1756?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16141503#comment-16141503
 ] 

stephen mallette commented on TINKERPOP-1756:
---------------------------------------------

ok - so you're using {{withRemote()}}. I don't think mocking {{Cluster}} and 
{{Client}} and other low-level objects is "nice". I've had to do it before for 
"simple" things and it's not fun. I also don't know that it would be good for 
this use case. the higher up the chain a mock is the closer you are to testing 
the code you want to test. While I could just make {{Cluster}} non-final so 
that you could do this, I'd rather come up with a better solution for easier 
mocking for everyone because {{withRemote()}} will be an often used capability 
and the demand for mocking will be there. So, perhaps we can work out a better 
solution together?

My initial thought was to just mock the {{RemoteConnection}} interface. I 
pictured people doing that for this use case when we designed {{withRemote()}}. 
that interface is also purposely simple because we want driver providers to 
implement it. If you mock {{RemoteConnection}} you completely bypass all the 
internals of {{Cluster}} and you only have to mock a single method which is 
much more clean:

{code}
public <E> RemoteTraversal<?, E> submit(Bytecode bytecode) throws 
RemoteConnectionException
{code}

The nice part about introducing the mock here is that you just need to return a 
{{RemoteTraversal}} which is an extension of {{Traversal}} itself. Why is that 
good? Because you can execute the bytecode against a local graph instance like 
TinkerGraph (or even the actual graph you are using if you can get an embedded 
instance of it) and then wrap it in a {{RemoteTraversal}} and your unit test 
case is complete. Of course, what I'm finding is that implementing 
{{RemoteTraversal}} is currently annoying for a "simple" mock. There are a lot 
of methods, many of which probably go unused for the {{withRemote()}} use case. 
I'm thinking about adding an {{InProcessRemoteTraversal}} class that basically 
will act as a default implementation for {{RemoteTraversal}} which can either 
work out of the box in the way I just described or act as a base class for 
extension if needed. In this way, the implementation of mock of 
{{RemoteConnection}} would just be:

{code}
    @Test
    public void testMock() throws Exception {
        final TinkerGraph remoteGraphToTest = TinkerFactory.createModern();
        final GraphTraversalSource remoteGToTest = 
remoteGraphToTest.traversal();

        Graph graph = EmptyGraph.instance();
        GraphTraversalSource g = graph.traversal().withRemote(new 
RemoteConnection() {
            @Override
            public <E> Iterator<Traverser.Admin<E>> submit(Traversal<?, E> 
traversal) throws RemoteConnectionException {
                return null;
            }

            @Override
            public <E> RemoteTraversal<?, E> submit(Bytecode bytecode) throws 
RemoteConnectionException {
                return new 
InProcessRemoteTraversal(JavaTranslator.of(remoteGToTest).translate(bytecode));
            }

            @Override
            public void close() throws Exception {

            }
        });

        assertEquals(6L, g.V().count().next().longValue());
    }
{code}

That test passes with some junky code I wrote so the concept is sound. in fact 
I could also make an {{InProcessRemoteConnection}} so you can just supply that 
to your {{withRemote()}} method and avoid having to mock all together:

{code}
g = graph.traversal().withRemote(new InProcessRemoteConnection(remoteGToTest));
{code}

That seems like an easy way to go without forcing folks to mock really complex 
classes like {{Cluster}}. What do you think?



> I wish Cluster was an interface so that I could mock it
> -------------------------------------------------------
>
>                 Key: TINKERPOP-1756
>                 URL: https://issues.apache.org/jira/browse/TINKERPOP-1756
>             Project: TinkerPop
>          Issue Type: Improvement
>          Components: driver
>    Affects Versions: 3.2.4
>            Reporter: Anish Doshi
>
> {{org.apache.tinkerpop.gremlin.driver.Cluster}} is currently a final class. 
> Which means that every time I need to mock this class, I cannot. I have to 
> create a separate object and mock that object instead of mocking {{Cluster}}.
> Is there a chance that Cluster can be changed to an interface, or at least 
> not have as a {{final}} class?
> Thanks.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to