(#) platform types should not be mocked
!!! ERROR: platform types should not be mocked
This is an error.
Id
: `DoNotMockPlatformTypes`
Summary
: platform types should not be mocked
Severity
: Error
Category
: Correctness
Platform
: Any
Vendor
: slack
Identifier
: slack-lint
Contact
: https://github.com/slackhq/slack-lints
Feedback
: https://github.com/slackhq/slack-lints
Min
: Lint 8.7+
Compiled
: Lint 8.7+
Artifact
: [com.slack.lint:slack-lint-checks](com_slack_lint_slack-lint-checks.md.html)
Since
: 0.4.0
Affects
: Kotlin and Java files and test sources
Editing
: This check runs on the fly in the IDE editor
Implementation
: [Source Code](https://github.com/slackhq/slack-lints/tree/main/slack-lint-checks/src/main/java/slack/lint/mocking/MockDetector.kt)
Tests
: [Source Code](https://github.com/slackhq/slack-lints/tree/main/slack-lint-checks/src/test/java/slack/lint/mocking/MockDetectorOptionsTest.kt)
Copyright Year
: 2021
Platform types (i.e. classes in java.*, android.*, etc) should not be
mocked. Use a real instance or fake instead. Mocking platform types like
these can lead to surprising test failures due to mocks that actually
behave differently than real instances, especially when passed into real
implementations that use them and expect them to behave in a certain
way. If using Robolectric, consider using its shadow APIs.
(##) Options
You can configure this lint checks using the following options:
(###) mock-annotations
A comma-separated list of mock annotations..
This property should define comma-separated list of mock annotation class names (FQCN). Set this for all issues using this option.
Default is "org.mockito.Mock,org.mockito.Spy".
Example `lint.xml`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~xml linenumbers
<lint>
<issue id="DoNotMockPlatformTypes">
<option name="mock-annotations" value=""org.mockito.Mock,org.mockito.Spy"" />
</issue>
</lint>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(###) mock-factories
A comma-separated list of mock factories (org.mockito.Mockito#methodName)..
A comma-separated list of mock factories (org.mockito.Mockito#methodName). Set this for all issues using this option.
Default is "org.mockito.Mockito#mock,org.mockito.Mockito#spy,slack.test.mockito.MockitoHelpers#mock,slack.test.mockito.MockitoHelpersKt#mock,org.mockito.kotlin.MockingKt#mock,org.mockito.kotlin.SpyingKt#spy".
Example `lint.xml`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~xml linenumbers
<lint>
<issue id="DoNotMockPlatformTypes">
<option name="mock-factories" value=""org.mockito.Mockito#mock,org.mockito.Mockito#spy,slack.test.mockito.MockitoHelpers#mock,slack.test.mockito.MockitoHelpersKt#mock,org.mockito.kotlin.MockingKt#mock,org.mockito.kotlin.SpyingKt#spy"" />
</issue>
</lint>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(###) mock-report
If enabled, writes a mock report to /build/reports/mockdetector/mock-report.csv..
If enabled, writes a mock report to /build/reports/mockdetector/mock-report.csv. The format of the file is a csv of (type,isError) of mocked classes. Set this for all issues using this option.
Default is "none".
Example `lint.xml`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~xml linenumbers
<lint>
<issue id="DoNotMockPlatformTypes">
<option name="mock-report" value=""none"" />
</issue>
</lint>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(##) Example
Here is an example of lint warnings produced by this check:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~text
test/slack/test/MyTests.kt:62:Error: platform type
'java.lang.Comparable' should not be mocked [DoNotMockPlatformTypes]
mockk<Comparable<String>>()
---------------------------
test/slack/test/MyTests.kt:63:Error: platform type 'java.lang.Runnable'
should not be mocked [DoNotMockPlatformTypes]
mockk<Runnable>()
-----------------
test/slack/test/MyTests.kt:65:Error: platform type
'kotlin.io.FileTreeWalk' should not be mocked [DoNotMockPlatformTypes]
mockk<FileTreeWalk>()
---------------------
test/slack/test/MyTests.kt:66:Error: platform type 'kotlin.Lazy' should
not be mocked [DoNotMockPlatformTypes]
mockk<Lazy<String>>()
---------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is the source file referenced above:
`test/slack/test/MyTests.kt`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~kotlin linenumbers
package slack.test
import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.SpyK
import io.mockk.mockk
import io.mockk.mockkClass
import io.mockk.mockkObject
import io.mockk.spyk
class MyTests {
@MockK lateinit var fieldDataMock: DataClass
@SpyK lateinit var fieldDataSpy: DataClass
fun dataClass() {
val localMock1: DataClass = mockk()
val localMock2 = mockk()
val localSpy1: DataClass = spyk()
val localSpy2 = spyk()
val localSpy3 = spyk(localMock1)
// KClass is not detected, explicit type needed!
val localClassMock = mockkClass(DataClass::class)
}
@MockK lateinit var fieldSealedMock: SealedClass
@SpyK lateinit var fieldSealedSpy: SealedClass
fun sealedClass() {
val localMock1: SealedClass = mockk()
val localMock2 = mockk()
val localSpy1: SealedClass = spyk()
val localSpy2 = spyk()
val localSpy3 = spyk(localMock1)
// KClass is not detected, explicit type needed!
val localClassMock = mockkClass(SealedClass::class)
}
@MockK lateinit var fieldObjectMock: ObjectClass
@SpyK lateinit var fieldObjectSpy: ObjectClass
fun objectClass() {
val localMock1: ObjectClass = mockk()
val localMock2 = mockk()
val localSpy1: ObjectClass = spyk()
val localSpy2 = spyk()
val localSpy3 = spyk(localMock1)
// KClass is not detected, explicit type needed!
val localClassMock = mockkClass(ObjectClass::class)
// Wrong Error: 'kotlin.Unit' is an object, so mocking it should not be necessary [DoNotMockObjectClass]
// Wrong Warning: platform type 'kotlin.Unit' should not be mocked [DoNotMockPlatformTypes]
// mockkObject(ObjectClass)
}
fun platformTypes() {
// java.
mockk>()
mockk()
// kotlin.
mockk()
mockk>()
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can also visit the
[source code](https://github.com/slackhq/slack-lints/tree/main/slack-lint-checks/src/test/java/slack/lint/mocking/MockDetectorOptionsTest.kt)
for the unit tests for this check to see additional scenarios.
The above example was automatically extracted from the first unit test
found for this lint check, `MockDetector.tests`.
To report a problem with this extracted sample, visit
https://github.com/slackhq/slack-lints.
(##) Including
!!!
This is not a built-in check. To include it, add the below dependency
to your project. This lint check is included in the lint documentation,
but the Android team may or may not agree with its recommendations.
```
// build.gradle.kts
lintChecks("com.slack.lint:slack-lint-checks:0.9.0")
// build.gradle
lintChecks 'com.slack.lint:slack-lint-checks:0.9.0'
// build.gradle.kts with version catalogs:
lintChecks(libs.slack.lint.checks)
# libs.versions.toml
[versions]
slack-lint-checks = "0.9.0"
[libraries]
# For clarity and text wrapping purposes the following declaration is
# shown split up across lines, but in TOML it needs to be on a single
# line (see https://github.com/toml-lang/toml/issues/516) so adjust
# when pasting into libs.versions.toml:
slack-lint-checks = {
module = "com.slack.lint:slack-lint-checks",
version.ref = "slack-lint-checks"
}
```
0.9.0 is the version this documentation was generated from;
there may be newer versions available.
[Additional details about com.slack.lint:slack-lint-checks](com_slack_lint_slack-lint-checks.md.html).
(##) Suppressing
You can suppress false positives using one of the following mechanisms:
* Using a suppression annotation like this on the enclosing
element:
```kt
// Kotlin
@Suppress("DoNotMockPlatformTypes")
fun method() {
problematicStatement()
}
```
or
```java
// Java
@SuppressWarnings("DoNotMockPlatformTypes")
void method() {
problematicStatement();
}
```
* Using a suppression comment like this on the line above:
```kt
//noinspection DoNotMockPlatformTypes
problematicStatement()
```
* Using a special `lint.xml` file in the source tree which turns off
the check in that folder and any sub folder. A simple file might look
like this:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="DoNotMockPlatformTypes" severity="ignore" />
</lint>
```
Instead of `ignore` you can also change the severity here, for
example from `error` to `warning`. You can find additional
documentation on how to filter issues by path, regular expression and
so on
[here](https://googlesamples.github.io/android-custom-lint-rules/usage/lintxml.md.html).
* In Gradle projects, using the DSL syntax to configure lint. For
example, you can use something like
```gradle
lintOptions {
disable 'DoNotMockPlatformTypes'
}
```
In Android projects this should be nested inside an `android { }`
block.
* For manual invocations of `lint`, using the `--ignore` flag:
```
$ lint --ignore DoNotMockPlatformTypes ...`
```
* Last, but not least, using baselines, as discussed
[here](https://googlesamples.github.io/android-custom-lint-rules/usage/baselines.md.html).