Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data provider mismatch with @Mocked annotation #337

Closed
AlexStasko opened this issue Sep 21, 2016 · 5 comments
Closed

Data provider mismatch with @Mocked annotation #337

AlexStasko opened this issue Sep 21, 2016 · 5 comments
Assignees

Comments

@AlexStasko
Copy link

AlexStasko commented Sep 21, 2016

I use JMockit 1.27
Java 1.8.92
And Windows OS

public class DummyServiceTest {

     private DummyService dummyService = new DummyService();

     @Test(expectedExceptions = {RuntimeException.class})
     public void testStore(@Mocked DummyDomain unused)  {
         new StrictExpectations() {
             {
                 new DummyDomain("TEST1");

                 try {
                     unused.exec();
                 } catch (IOException e) {
                     // never happen
                }
                result = new IOException();
             }
         };

         dummyService.store("test");
     }
}

Report prints following error:

org.testng.internal.reflect.MethodMatcherException: 
Data provider mismatch
Method: testStore([Parameter{index=0, type=by.common.model.DummyDomain, declaredAnnotations=[@mockit.Mocked(stubOutClassInitialization=false)]}])
Arguments: [(java.lang.String)]
at org.testng.internal.reflect.DataProviderMethodMatcher.getConformingArguments(DataProviderMethodMatcher.java:52)
at org.testng.internal.Invoker.injectParameters(Invoker.java:1238)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1131)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
at org.testng.TestRunner.privateRun(TestRunner.java:749)
at org.testng.TestRunner.run(TestRunner.java:603)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:368)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:363)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:321)
at org.testng.SuiteRunner.run(SuiteRunner.java:270)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1284)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1209)
at org.testng.TestNG.runSuites(TestNG.java:1124)
at org.testng.TestNG.run(TestNG.java:1096)
at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.runTests(TestNGTestClassProcessor.java:130)
at org.gradle.api.internal.tasks.testing.testng.TestNGTestClassProcessor.stop(TestNGTestClassProcessor.java:80)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:58)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

That problem happens with testng 6.9.11 and higher. With testng 6.9.10 this test runs successfully.
I am not sure the problem is in jmockit, but might be this is an issue somewhere in proxy that jmockit creates for method parameter.

Test project is here jmockit-check.zip

Thank you,
Alex

@AlexStasko AlexStasko changed the title Coverage tool: Data provider mismatch with @Mocked annotation Data provider mismatch with @Mocked annotation Sep 21, 2016
@juherr
Copy link

juherr commented Sep 21, 2016

The problem is due to the new way to manage data provider parameters: testng-team/testng#923

Maybe JMockit should upgrade its TestNG support. But let me know if a specific spi is needed to help with the integration.

Ping @nitinverma who made the 6.9.11 modification, maybe he'll have a good idea for a nice integration.

For reference, we have testng-team/testng#600 in the backlog too which points some integration problems on dataprovider.

@rliesenfeld
Copy link
Member

rliesenfeld commented Sep 21, 2016

TestNG should provide an extensible mechanism for third-party libraries to provide their own custom arguments to test methods, without them having to resort to hacks as I had to do in JMockit. JUnit 5 (not JUnit 4) does provide such a mechanism (the ParameterResolver extension interface), and it is used in JMockit.

I will see if the new parameter resolution in TestNG 6.9.11+can be supported. From the first look, it may be difficult. I don't exclude the possibility that mock parameters in test methods won't be usable anymore with these newer versions of TestNG; in that case, JMockit users would have to limit themselves to mock fields.

@nitinverma
Copy link

Hi @AlexStasko, @rliesenfeld

testng is expecting an object that is an instance of 'DummyDomain' or null, as both are valid inputs to invoke this test method.

Following snippet would satisfy testng-6.9.11 for now.

   @DataProvider(name = "data")
    public Object[][] data() {
        return new Object[][]{
                new Object[]{null},
                new Object[]{new DummyDomain("from-data-provider")},
        };
    }

    @Test(dataProvider = "data", expectedExceptions = {RuntimeException.class})
    public void testStore(@Mocked DummyDomain unused) {
        System.out.println("unused:" + unused);
        new StrictExpectations() {
            {
                new DummyDomain("TEST1");

                try {
                    unused.exec();
                } catch (IOException e) {
                    // never happen
                }
                result = new IOException();
            }
        };

        dummyService.store("test");
    }

Happy to help n collaborate on this integration.

Regards,

Nitin Verma

@nitinverma
Copy link

Refer https://github.com/jmockit/jmockit1
if getInjectedParameter(...) returns corresponding mock object in place of the empty string. Above test should start working. What additional context would you require to build a mock?

TestNGRunnerDecorator.java

   public static final class MockParameters extends MockUp<Parameters>
   {
      @Mock
      public static void checkParameterTypes(
         String methodName, Class<?>[] parameterTypes, String methodAnnotation, String[] parameterNames) {}

      @Mock
      @Nullable
      public static Object getInjectedParameter(
         @Nonnull Invocation invocation, Class<?> c, @Nullable Method method,
         ITestContext context, ITestResult testResult)
      {
         ((MockInvocation) invocation).prepareToProceedFromNonRecursiveMock();
         Object value = Parameters.getInjectedParameter(c, method, context, testResult);

         if (value != null) {
            return value;
         }

         if (method == null) {
            // Test execution didn't reach a test method yet.
            return null;
         }

         if (method.getParameterTypes().length == 0) {
            // A test method was reached, but it has no parameters.
            return null;
         }

         if (isMethodWithParametersProvidedByTestNG(method)) {
            // The test method has parameters, but they are to be provided by TestNG, not JMockit.
            return null;
         }

         // It's a mock parameter in a test method, to be provided by JMockit.
         return "";
      }
   }

@Milbor-zz
Copy link

It stopped working for testng 6.12. Reopen?

    @Test
    public void test(@Injectable Runnable runnable) {
    }

org.testng.internal.reflect.MethodMatcherException:
Data provider mismatch
Method: test([Parameter{index=0, type=java.lang.Runnable, declaredAnnotations=[@mockit.Injectable(value=)]}])
Arguments: []

at org.testng.internal.reflect.DataProviderMethodMatcher.getConformingArguments(DataProviderMethodMatcher.java:45)
at org.testng.internal.Invoker.injectParameters(Invoker.java:1301)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

5 participants