I'm attempting (still) to learn the ins and outs of JMockit. Here's yet another example of a JMockit oddity I just don't get. Running the test with NonStrictExpectations works just fine. However, running with MockUp does not. I'm not sure why. Any ideas? I'm running JMockit 1.5.
Method to test:
private List<Foo> getFooList(List<FooStatement> fooStatements){
List<Foo> FooList = new ArrayList<Foo>();
for(FooStatement at: fooStatements){
List<Foo> aList = at.getFoos();
FooList.addAll(aList);
}
return FooList;
}
Successful Expectations Test
@Test
public void getFooListWithExpectationsTest(
@Mocked final FooStatement mockFooStatement,
@Mocked final Foo mockFoo
){
List<FooStatement> fooStatementList = new ArrayList<>(Arrays.asList(
mockFooStatement,
mockFooStatement
));
new NonStrictExpectations(){{
mockFooStatement.getFoos();
result = new ArrayList<Foo>(Arrays.asList(mockFoo));
}};
List<Foo> fooList = Deencapsulation.invoke(handler, "getFooList", fooStatementList);
Assert.assertTrue(fooList.size() == 2);
}
Assertions Error (0 != 2) with MockUp
@Test
public void getFooListWithMockUpTest(
@Mocked final FooStatement mockFooStatement,
@Mocked final Foo mockFoo
){
new MockUp<FooStatement>(){
@Mock
public List<Foo> getFoos(){
return new ArrayList<Foo>(Arrays.asList(mockFoo));
}
};
List<FooStatement> fooStatementList = new ArrayList<>(Arrays.asList(
mockFooStatement,
mockFooStatement
));
List<Foo> fooList = Deencapsulation.invoke(handler, "getFooList", fooStatementList);
Assert.assertTrue(fooList.size() == 2);
}
An expectation represents a set of invocations to a specific mocked method/constructor that is relevant for a given test. An expectation may cover multiple different invocations to the same method or constructor, but it doesn't have to cover all such invocations that occur during the execution of the test.
JMockit's Mockup API provides support for the creation of fake implementations or mock-ups. Typically, a mock-up targets a few methods and/or constructors in the class to be faked, while leaving most other methods and constructors unmodified.
First of all, let's talk about what JMockit is: a Java framework for mocking objects in tests (you can use it for both JUnit and TestNG ones). It uses Java's instrumentation APIs to modify the classes' bytecode during runtime in order to dynamically alter their behavior.
Instance mocking means that a statement like: $obj = new \MyNamespace\Foo; …will actually generate a mock object. This is done by replacing the real class with an instance mock (similar to an alias mock), as with mocking public methods.
You are using MockUp<?>
incorrectly. MockUp<T?
will tell JMockit to redefine a classes loaded to JVM so that instead of the real class initialization of FooStatement
, it will replace them by the ones defined in the MockUp<FooStatement
.
So basically MockUp<FooStatement>
will automatically replace calls of new FooStatement()
.
Try something like:
@Test
public void getFooListWithMockUpTest(@Mocked final Foo mockFoo){
new MockUp<FooStatement>(){
@Mock
public List<Foo> getFoos(){
return new ArrayList<Foo>(Arrays.asList(mockFoo));
}
};
List<FooStatement> fooStatementList = new ArrayList<>(Arrays.asList(
new FooStatement(),
new FooStatement()
));
List<Foo> fooList = Deencapsulation.invoke(handler, "getFooList", fooStatementList);
Assert.assertTrue(fooList.size() == 2);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With