Uploaded image for project: 'Rules Repository'
  1. Rules Repository
  2. RSPEC-5969

Mocking all non-private methods of a class should be avoided

    XMLWordPrintable

    Details

    • Type: Code Smell Detection
    • Status: Active
    • Resolution: Unresolved
    • Labels:
    • Message:
      Refactor this test instead of mocking every non-private member of this class.
    • Highlighting:
      Hide

      Primary location: mock variable declaration.
      Secondaries: mocked methods.

      Show
      Primary location: mock variable declaration. Secondaries: mocked methods.
    • Default Severity:
      Critical
    • Impact:
      High
    • Likelihood:
      Low
    • Default Quality Profiles:
      Sonar way
    • Covered Languages:
      Java
    • Remediation Function:
      Constant/Issue
    • Constant Cost:
      10min
    • Analysis Scope:
      Test Sources

      Description

      If you end up mocking every non-private method of a class in order to write tests, it is a strong sign that your test became too complex, or that you misunderstood the way you are supposed to use the mocking mechanism.
      You should either refactor the test code into multiple units, or consider using the class itself, by either directly instantiating it, or creating a new one inheriting from it, with the expected behavior.

      This rule reports an issue when every member of a given class are mocked.

      Noncompliant Code Example

      @Test
      void test_requiring_MyClass() {
        MyClass myClassMock = mock(MyClass.class); // Noncompliant
        when(myClassMock.f()).thenReturn(1);
        when(myClassMock.g()).thenReturn(2);
        //...
      }
      
      abstract class MyClass {
        abstract int f();
        abstract int g();
      }
      

      Compliant Solution

      @Test
      void test_requiring_MyClass() {
        MyClass myClass = new MyClassForTest();
        //...
      }
      
      class MyClassForTest extends MyClass {
      
        @Override
        int f() {
          return 1;
        }
      
        @Override
        int g() {
          return 2;
        }
      }
      

      or

      @Test
      void test_requiring_f() {
        MyClass myClassMock = mock(MyClass.class);
        when(myClassMock.f()).thenReturn(1);
        //...
      }
      
      @Test
      void test_requiring_g() {
        MyClass myClassMock = mock(MyClass.class);
        when(myClassMock.g()).thenReturn(2);
        //...
      }
      
      abstract class MyClass {
        abstract int f();
        abstract int g();
      }
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              quentin.jaquier Quentin Jaquier
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated: