×
Crocus
공부한 내용을 정리하는 블로그로 시작한
Crocus는 2014년 1월 14일 부터 시작하여
현재 월 6만명, 총 1,583,131명의 방문자 수를 기록하고 있습니다.
Donation
이제 많은 사용자들이 이용하는 만큼
더 다양한 서비스 개발/제공을 위해 후원금을 모금하고자 합니다.
후원을 해주시는 분들은 Donators 명단에 성명, 후원금을 기입해드리며
Crocus 블로그가 아닌 다른 곳에 정리해둔 저만의 내용을 공유해 드리고자 합니다.
Account
예금주 : 고관우
신한은행 : 110-334-866541
카카오뱅크 : 3333-01-7888060

👉 후원 페이지 바로가기 Donators
익명 : 5000원(Crocus응원합니다.)
busyhuman: 5000원(유용한 지식 감사합니다.)
익명 : 5000원(알고리즘 학습러)
728x90
반응형

아래와 같이 간단한 클래스가 있다고 가정해보자.

 

package com.example.mockedstaticunittest;

public class Calculator {
    public static int add(int x, int y) {
        return x + y;
    }

    public int sub(int x, int y) {
        return x - y;
    }
}

 

해당 코드의 sub를 테스트를 하면 아래와 같다.

    @Test
    public void execute_sub() {
        Calculator calculator = new Calculator();

        // when
        int sub = calculator.sub(20, 10);

        // then
        assertEquals(sub, 10);
    }
Process finished with exit code 0

 

하지만 static인 add를 테스트 하면 아래와 같아진다.

    @Test
    public void execute_add() {
        int a = 1, b = 2;
        when(Calculator.add(a, b)).thenReturn(a + b);

        int sum = Calculator.add(a, b);

        assertEquals(a + b, sum);
    }
org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.


	at com.example.mockedstaticunittest.CalculatorTest.execute_add(CalculatorTest.java:12)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

 

static 메서드를 테스트 할 수 없는 상황이 왔고 이를 해결하기 위해 이번에는 Mockito를 이용하여 static method를 해결하는 방법을 알아보고자 한다.

 

 

asolntsev.github.io/en/2020/07/11/mockito-static-methods/

 

Mockito can mock static methods! · Andrei Solntsev

Mockito can mock static methods! 11 Jul 2020 Hot news! Mockito just released version 3.4.0 which can now mock static methods. Before 3.4.0, Mockito could not mock static methods. It could only mock non-static methods. Though, PowerMock could. But PowerMock

asolntsev.github.io

 

우선 build.gradle에서 dependency에 testImplementation('org.mockito:mockito-inline:3.4.0')를 추가해준다.

 

3.4.0버전부터 MockedStatic라는 새로운 기능이 들어감으로써 우리는 PowerMock가 아닌 Mockito를 이용하여서도 static method를 테스트할 수 있게 되었다.

 

아래와 같이 MockedStatic객체를 선언한다.

private static MockedStatic<Calculator> mCalculator;

 

그리고 해당 MockedStatic를 mockStatic 메서드를 이용하여 beforeClass에서 모킹하고 afterClass에서 해제해준다.

    @BeforeClass
    public static void beforeClass() {
        mCalculator = mockStatic(Calculator.class);
    }

    @AfterClass
    public static void afterClass() {
        mCalculator.close();
    }

 

다시 static add method를 테스트해준다. 이때 Calculator.add(anyInt(), anyInt()).thenReturn(a+b)을 이용하여 해당 static method를 모킹해주면 이제 해당 스태틱 메서드를 사용할 수 있게 된다.

    @Test
    public void execute_add() {
        int a = 1, b = 2;
        when(Calculator.add(anyInt(), anyInt())).thenReturn(a + b);

        int sum = Calculator.add(a, b);

        assertEquals(a + b, sum);
    }

 

아래는 전체 코드이다.

package com.example.mockedstaticunittest;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.MockedStatic;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class CalculatorTest {
    private static MockedStatic<Calculator> mCalculator;

    @BeforeClass
    public static void beforeClass() {
        mCalculator = mockStatic(Calculator.class);
    }

    @AfterClass
    public static void afterClass() {
        mCalculator.close();
    }

    @Test
    public void execute_add() {
        int a = 1, b = 2;
        when(Calculator.add(anyInt(), anyInt())).thenReturn(a + b);

        int sum = Calculator.add(a, b);

        assertEquals(a + b, sum);
    }
}

 

반응형