Reputation: 4055
We are currently using Mockito + PowerMock as our main mocking framework and had a few issues with this once started moving some of our code to java 8. Because of this we decided to evaluate jMockit as an alternative. I have quite a good understanding of mocking concepts but I admit that my experience with jMockit is very limited.
However I am having problems with testing something that in my view should be very basic: the class under test creates an instance of some other class inside its constructor using new. That new invocation is the thing that I would like to make return a mock instance.
Here is the code like the one I am using: package com.some.org.some.app;
import mockit.Expectations;
import mockit.Injectable;
import mockit.Mocked;
import org.testng.annotations.Test;
public class ClassUnderTestTest {
interface SomeService {
void doWork();
}
class ClassUnderTest {
private final SomeService service;
public ClassUnderTest() {
this.service = new SomeService() {
@Override
public void doWork() {
}
};
}
}
@Injectable
private SomeService mockService;
@Test
public void shouldBeAbleToMaskVariousNumbers() throws Exception {
new Expectations() {{
new ClassUnderTest();
result = mockService;
}};
}
}
When running the above I am getting the exception below:
java.lang.IllegalStateException: Missing invocation to mocked type at this point;
please make sure such invocations appear only after the declaration of a suitable
mock field or parameter
I am using TestNG as a testing framework and in reality my test method has a bunch of parameters as it is expecting some test data being passed by a data provider.
This is pretty basic and it looks like my approach is not the jMockit way. Thank you in advance for your support.
Upvotes: 1
Views: 3578
Reputation: 16380
This is very easy to do with JMockit:
public class ClassUnderTestTest {
interface SomeService { int doWork(); }
class ClassUnderTest {
private final SomeService service;
ClassUnderTest() {
service = new SomeService() {
@Override public int doWork() { return -1; }
};
}
int useTheService() { return service.doWork(); }
}
// This annotation is a variation on @Mocked, which extends
// mocking to any implementation classes or subclasses of
// the mocked base type.
@Capturing SomeService mockService;
@Test
public void shouldBeAbleToMaskVariousNumbers() {
new Expectations() {{ mockService.doWork(); result = 123; }};
int n = new ClassUnderTest().useTheService();
assertEquals(123, n);
}
}
Upvotes: 3