@Test
  public void testInvokeWithParameterizedClassAndVariableReturnType() {
    String s =
        StatementBuilder.create(Context.create().autoImport())
            .declareVariable(
                "set",
                Set.class,
                StatementBuilder.create().invokeStatic(Foo.class, "baz", Set.class))
            .toJavaString();

    assertEquals(
        "Failed to generate method invocation with variable return type inferred from Class<T>",
        "Set set = Foo.baz(Set.class);",
        s);
  }
  @Test
  public void testInvokeWithVariableReturnType() {
    String s =
        StatementBuilder.create(Context.create().autoImport())
            .declareVariable("s", String.class)
            .declareVariable(
                "str",
                String.class,
                StatementBuilder.create().invokeStatic(Foo.class, "foo", Variable.get("s")))
            .toJavaString();

    assertEquals(
        "Failed to generate method invocation using variable return type",
        "String str = Foo.foo(s);",
        s);
  }
  @Test
  public void testInvokeWithParameterizedListAndVariableReturnType() {
    String s =
        StatementBuilder.create(Context.create().autoImport())
            .declareVariable("list", new TypeLiteral<List<String>>() {})
            .declareVariable(
                "str",
                String.class,
                StatementBuilder.create().invokeStatic(Foo.class, "bar", Variable.get("list")))
            .toJavaString();

    assertEquals(
        "Failed to generate method invocation with variable return type inferred from List<T>",
        "String str = Foo.bar(list);",
        s);
  }
  @Test
  public void testInvokeStaticMethod() {
    String s =
        StatementBuilder.create().invokeStatic(Integer.class, "getInteger", "123").toJavaString();

    assertEquals("Failed to generate static method invocation", "Integer.getInteger(\"123\")", s);
  }
  @Test
  public void testInvokeWithParameterizedMapAndVariableReturnType() {
    String s =
        StatementBuilder.create(Context.create().autoImport())
            .declareVariable("map", new TypeLiteral<Map<String, Integer>>() {})
            .declareVariable(
                "val",
                Integer.class,
                StatementBuilder.create().invokeStatic(Foo.class, "bar", Variable.get("map")))
            .toJavaString();

    assertEquals(
        "Failed to generate method invocation with variable return type inferred from Map<K, V>",
        "Integer val = Foo.bar(map);",
        s);
  }
  @Test
  public void testInvokeOnLiteral() {
    String result = StatementBuilder.create().loadLiteral("foo").invoke("toString").toJavaString();

    assertEquals(
        "Failed to generate invocation using literal parameters", "\"foo\".toString()", result);
  }
  @Test
  public void testInvokeWithInvalidVariableReturnType() {

    try {
      StatementBuilder.create(Context.create().autoImport())
          .declareVariable("list", new TypeLiteral<List<String>>() {})
          .declareVariable(
              "n",
              Integer.class,
              StatementBuilder.create().invokeStatic(Foo.class, "bar", Variable.get("list")))
          .toJavaString();
      fail("expected InvalidTypeException");
    } catch (InvalidTypeException e) {
      // expected
    }
  }
  @Test
  public void testInvokeUsingStandardizedLoadVariableInstance() {
    Context context = ContextBuilder.create().addVariable("s", String.class).getContext();

    Variable v = Variable.create("s", String.class);
    String s = StatementBuilder.create(context).load(v).invoke("toUpperCase").toJavaString();

    assertEquals("Failed using load() passing a variable instance", "s.toUpperCase()", s);
  }
 @Test
 public void testInvokeUndefinedStaticMethod() {
   try {
     StatementBuilder.create().invokeStatic(Integer.class, "intValue").toJavaString();
     fail("expected UndefinedMethodException");
   } catch (UndefinedMethodException udme) {
     assertEquals("Wrong exception details", udme.getMethodName(), "intValue");
   }
 }
  @Test
  public void testSingleInvocation() {
    String s =
        StatementBuilder.create()
            .declareVariable("obj", Object.class)
            .loadVariable("obj")
            .invoke("toString")
            .toJavaString();

    assertEquals("Failed to generate invocation on variable", "obj.toString()", s);
  }
  @Test
  public void testInvokeWithParameterTypeConversionOfStringToInteger() {
    String s =
        StatementBuilder.create()
            .declareVariable("str", String.class)
            .loadVariable("str")
            .invoke("substring", "1", "3")
            .toJavaString();

    assertEquals(
        "Failed to generate invocation with parameter type conversion", "str.substring(1, 3)", s);
  }
  @Test
  public void testInvokeWithParameterTypeConversionOfIntegerToString() {
    String s =
        StatementBuilder.create()
            .declareVariable("str", String.class)
            .loadVariable("str")
            .invoke("endsWith", 123)
            .toJavaString();

    assertEquals(
        "Failed to generate invocation with parameter type conversion", "str.endsWith(\"123\")", s);
  }
  @Test
  public void testInvokeBestMatchingMethod() {
    String s =
        StatementBuilder.create()
            .declareVariable("n", Integer.class)
            .loadVariable("n")
            // 1 will be inferred to LiteralValue<Integer>, equals(Integer.class)
            // should be matched equals(Object.class)
            .invoke("equals", 1)
            .toJavaString();

    assertEquals("Failed to generate invocation on matched method", "n.equals(1)", s);
  }
  @Test
  public void testInvokeWithLiteralParameters() {
    String result =
        StatementBuilder.create()
            .declareVariable("s", String.class)
            .loadVariable("s")
            .invoke("replaceAll", "foo", "foo\t\n")
            .toJavaString();

    assertEquals(
        "Failed to generate invocation using literal parameters",
        "s.replaceAll(\"foo\", \"foo\\t\\n\")",
        result);
  }
 @Test
 public void testInvokeOnUndefinedVariable() {
   try {
     // injector undefined
     StatementBuilder.create()
         .loadVariable("injector")
         .invoke("provide", Refs.get("param"), Refs.get("param2"))
         .toJavaString();
     fail("expected OutOfScopeException");
   } catch (OutOfScopeException oose) {
     // expected
     assertTrue("Wrong exception thrown", oose.getMessage().contains("injector"));
   }
 }
 @Test
 public void testInvokeUndefinedMethodOnVariable() {
   try {
     StatementBuilder.create()
         .declareVariable("obj", Object.class)
         .declareVariable("param", String.class)
         .loadVariable("obj")
         .invoke("undefinedMethod", Variable.get("param"))
         .toJavaString();
     fail("expected UndefinedMethodException");
   } catch (UndefinedMethodException udme) {
     // expected
     assertEquals("Wrong exception thrown", udme.getMethodName(), "undefinedMethod");
   }
 }
  @Test
  public void testInvokeWithParameterTypeConversionOfVariable() {
    Context c = Context.create().addVariable("n", Integer.class, 123);
    String s =
        StatementBuilder.create(c)
            .declareVariable("str", String.class)
            .loadVariable("str")
            .invoke("endsWith", c.getVariable("n").getValue())
            .toJavaString();

    assertEquals(
        "Failed to generate invocation with parameter type conversion of variable",
        "str.endsWith(\"123\")",
        s);
  }
 @Test
 public void testInvokeWithUndefinedVariable() {
   try {
     // param2 undefined
     StatementBuilder.create()
         .declareVariable("obj", Object.class)
         .declareVariable("param", String.class)
         .loadVariable("obj")
         .invoke("undefinedMethod", Variable.get("param"), Variable.get("param2"))
         .toJavaString();
     fail("expected OutOfScopeException");
   } catch (OutOfScopeException oose) {
     // expected
     assertTrue(oose.getMessage().contains("param2"));
   }
 }
  @Test
  public void testChainedInvocations() {
    String s =
        StatementBuilder.create()
            .declareVariable("i", Integer.class)
            .declareVariable("regex", String.class)
            .declareVariable("replacement", String.class)
            .loadVariable("i")
            .invoke("toString")
            .invoke("replaceAll", Variable.get("regex"), Variable.get("replacement"))
            .toJavaString();

    assertEquals(
        "Failed to generate chained invocations on variable",
        "i.toString().replaceAll(regex, replacement)",
        s);
  }
 @Test
 public void testInvokeChainedUndefinedMethod() {
   try {
     StatementBuilder.create()
         .declareVariable("s", String.class)
         .declareVariable("regex", String.class)
         .declareVariable("replacement", String.class)
         .loadVariable("s")
         .invoke("replaceAll", Variable.get("regex"), Variable.get("replacement"))
         .invoke("undefinedMethod", Variable.get("regex"), Variable.get("replacement"))
         .toJavaString();
     fail("expected UndefinedMethodException");
   } catch (UndefinedMethodException udme) {
     // expected
     assertEquals("Wrong exception thrown", udme.getMethodName(), "undefinedMethod");
   }
 }
  @Test
  public void testInvokeUsingStandardizedLoadLiteral() {
    String s = StatementBuilder.create().load("foo").invoke("toUpperCase").toJavaString();

    assertEquals("Failed injecting literal with load()", "\"foo\".toUpperCase()", s);
  }