可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm removing Powermock from the project I'm currently working on, so I'm trying to rewrite some existing unitary test only with Mockito (mockito-core-2.2.28).
When I run the test, I have the following error:
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class com.ExternalpackagePath.Externalclass
Mockito cannot mock/spy because :
I know that this question has already been asked (How to mock a final class with mockito, Mock objects calling final classes static methods with Mockito), but I didn't find the answer I'm looking for.
Here is an extract of my code :
public class MyClassToTest extends TestCase { private MyClass myClass; @Mock private Externalclass ext; // This class is final, I would like to mock it @Override protected void setUp() throws Exception { MockitoAnnotations.initMocks(this); // <<<< The exception is thrown here ext = Mockito.mock(Externalclass.class); } }
As mentioned in the Mockito documentation (https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2, §Mock the unmockable), I added the org.mockito.plugins.MockMaker file. This is the tree of my project :
- project
- src
- com.packagePath.myPackage
- test
- com.packagePath.myPackage
- resources
- mockito-extensions
- org.mockito.plugins.MockMaker
I also tries to put the "resources" directory in "src", in a subdir called "test", but the result is still the same.
I thought that mocking a final was possible with Mockito v2. Does someone have an idea of what is missing here ?
Thanks!
回答1:
Weird that your solution seems to work.
According to their documentation on Github it says.
Mocking of final classes and methods is an incubating, opt-in feature. It uses a combination of Java agent instrumentation and subclassing in order to enable mockability of these types. As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
containing a single line:
mock-maker-inline
After you created this file, Mockito will automatically use this new engine and one can do :
final class FinalClass { final String finalMethod() { return "something"; } } FinalClass concrete = new FinalClass(); FinalClass mock = mock(FinalClass.class); given(mock.finalMethod()).willReturn("not anymore"); assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());
In subsequent milestones, the team will bring a programmatic way of using this feature. We will identify and provide support for all unmockable scenarios. Stay tuned and please let us know what you think of this feature!
My working structure now looks like this.
回答2:
I couldn't get it working with the configuration file either; however, the Mockito team is so kind and also provides a pre-configured Mockito artifact that requires no configuration in the target project.
So, if you use Gradle and want to test your Kotlin code, just add this to your project's dependencies:
testCompile 'org.mockito:mockito-inline:2.8.9' testCompile('com.nhaarman:mockito-kotlin:1.5.0') { exclude group: 'org.jetbrains.kotlin' exclude group: 'org.mockito' }
回答3:
Well, I found what's wrong here, it maybe useful for other people. My project tree is wrong, I put the org.mockito.plugins.MockMaker in a directory "mockito-extension" directly in "src". This is my tree now:
- projet
- src
- com.packagePath.myPackage
- mockito-extensions
- org.mockito.plugins.MockMaker
- test
- com.packagePath.myPackage
回答4:
You seem to have had a classpath issue, just like I did.
Your previous setup would have also worked, but it seems like
project/test/resources
was not in your classpath.
I had the same issue when I tried to run this with IntelliJ. I simply marked the resources directory as a Test Resources Root and it worked fine. Praise the gods of Mockito!
回答5:
This solution worked for me: Instead of
testCompile "org.mockito:mockito-android:2.9.0"
in the gradle file, replace it with
testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.9.0'
and it would work.