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

Expectation recorded on superclass method gets overwritten #209

Closed
Milbor opened this Issue Sep 17, 2015 · 2 comments

Comments

2 participants
@Milbor

Milbor commented Sep 17, 2015

Expectation recorded on superclass method on subclass object is overwritten if same expectation is recorded on different subclass object.

Best shown on following unit test (testng 6.9.6, jmockit 1.19) which I would expect to pass.
Is it bug? If not, could you elaborate on why it fails?

public class SpikeTest {
    public static class First extends Parent {
    }

    public static class Second extends Parent {
    }

    public static abstract class Parent {
        public String getValue() {
            return "parent";
        }
    }

    @Mocked
    private First first;
    @Mocked
    private Second second;

    @Test
    public void test() throws Exception {
        new Expectations() {{
            first.getValue();
            result = "first";

            second.getValue();
            result = "second"; //this recording overwrites previous recording on first object
        }};
        assertEquals(second.getValue(), "second");
        assertEquals(first.getValue(), "first"); //fails here, recorded "first" value is overwritten by "second"
    }
}
@rliesenfeld

This comment has been minimized.

Show comment
Hide comment
@rliesenfeld

rliesenfeld Sep 17, 2015

Member

It's not a bug, even if in a case like this the mocking behavior is not what one would expect; well, unless you are familiar with the exact semantics of @Mocked.

Expectations recorded/verified on a @Mocked instance, by default, do not care about the actual instance used during replay (the one the code under test used); they will match regardless, considering only which method was called and any arguments and argument matchers.

If the instance on which the expectation was recorded needs to match the instances at replay time, then the test should use @Injectable rather than @Mocked. Alternatively, the test can use the "onInstance(mocked instance)" constraint to force instance matching.

Member

rliesenfeld commented Sep 17, 2015

It's not a bug, even if in a case like this the mocking behavior is not what one would expect; well, unless you are familiar with the exact semantics of @Mocked.

Expectations recorded/verified on a @Mocked instance, by default, do not care about the actual instance used during replay (the one the code under test used); they will match regardless, considering only which method was called and any arguments and argument matchers.

If the instance on which the expectation was recorded needs to match the instances at replay time, then the test should use @Injectable rather than @Mocked. Alternatively, the test can use the "onInstance(mocked instance)" constraint to force instance matching.

@rliesenfeld rliesenfeld self-assigned this Sep 18, 2015

@rliesenfeld

This comment has been minimized.

Show comment
Hide comment
@rliesenfeld

rliesenfeld Sep 18, 2015

Member

Perhaps @Mocked semantics can be improved here; I am thinking to add a check that the class of any mocked instance is the same as the @Mocked class, when comparing expectations and matching invocations to expectations.

Member

rliesenfeld commented Sep 18, 2015

Perhaps @Mocked semantics can be improved here; I am thinking to add a check that the class of any mocked instance is the same as the @Mocked class, when comparing expectations and matching invocations to expectations.

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