문제

이것은 일반적인 질문하는 방법에 대한 단위 테스트 Java 클래스를 사용하여 모의 개체입니다.
I 요약 할 수 있습니다 내 문제로 이것은 예입니다.
말하자 나는 인터페이스는 불 MyInterface.java 그리고"TwoString"되지 않는 객체를 재정의 equals()

"TwoString.java"

   private String string1;
   private String string2;

   public TwoString(String string1, String string2) {
     this.string1 = string1;
     this.string2 = string2;
   }
   ...getters..setters..

"MyInterface.java"

void callMe(TwoString twoString);

"MyClass.java" 체입니다.그것의 생성자를 받 콘크리트의 구현 MyInterface.
MyClass methodToTest()들을 만들기 위한 논리 TwoString oject 에서 어떤 방법입니다.말하자는 것으로 생성

new TwoString("a","b")

그래서 때 methodToTest()를 호출을 만들이 TwoString 개체가 전달될 인터페이스 방법 callMe(TwoString twoString).

기본적으로 내가 원하는 모의하는 인터페이스입니다.을 만들 MyClass 체 이 mock.다음 확인하는 모의 방법이라고의 특정 인스턴스와 TwoString.

내가 사용하여 EasyMock 과 이것이 일부 자바 코드

"MyClassTest.java"

public void test() throws Exception {   
   MyInterface myInterfaceMock = createMock(MyInterface.class);
   MyClass myClass = new MyClass(myInterfaceMock);

   myInterfaceMock.callMe(new TwoString("a","b"));   <--- fails here
   expectLastCall();
   replay(myInterfaceMock);

   myClass.methodToTest();
   verify(myInterfaceMock);

여기에 문제가 온다.이 TwoString 는 개체의 예에는 전화

myInterfaceMock.callMe(new TwoString("a","b"));

다른 하나에서 생성 MyClass.methodToTest()기 TwoString.java 재정의되지 않 같습니다.

내 건너뛸 수 있는 문제에 TwoString 사용하여 인스턴스

myInterfaceMock.callMe((TwoString)anyObject());

그러나 내가 있는지 확인하려면 인터페이스 메서드를 호출하는 특정의 인스턴스 TwoString 포함된"a"를 string1 과"b"로 string2.

이 경우 TwoString 객체에는 매우 간단하며,그것은 쉬운 것입니다 equals 메서드를 재정의해야 합니다-하지만 무엇이 필요한 경우 확인하는 더 복잡한 객체입니다.

감사

편집:

수 있도록 노력하겠습니다 그것은 더 읽으로 이 예제

public class MyClassTest {
    private MyClass myClass;
    private TaskExecutor taskExecutorMock;

    @Before
    public void setUp() throws Exception {
        taskExecutorMock = createMock(TaskExecutor.class);
        myClass = new MyClass(taskExecutorMock);
    }

    @Test
    public void testRun() throws Exception {
        List<MyObj> myObjList = new ArrayList<MyObj>();
        myObjList.add(new MyObj("abc", referenceToSomethingElse));

        taskExecutorMock.execute(new SomeTask(referenceToSomethingElse,  ???new SomeObj("abc", referenceToSomethingElse, "whatever")));   <--- ??? = object created using data in myObjList
        expectLastCall();
        replay(taskExecutorMock);

        myClass.run(myObjList);

        verify(taskExecutorMock);
    }
}

???SomeObj =체에 의해 만들어 myClass.run()를 사용하여 데이터에 포함된 myObjList.
말 SomeObj 에서 타사 라이브러리고 재정의되지 않 같습니다.

내가 원하는지 확인하는 것 taskExecutorMock.execute()방법이라는 특정의 인스턴스는 SomeObj

는 방법을 테스트할 수 있습니 myClass.run()가 실제로 부르 taskExecutorMock 방법으로 올바른 인스턴스

도움이 되었습니까?

해결책

사용자 정의 평등 일치 방법을 사용할 수 있습니다. org.easymock.IArgumentMatcher.

그것은 다음과 같은 것처럼 보일 것입니다.

private static <T extends TwoString> T eqTwoString(final TwoString twoString) {
    reportMatcher(new IArgumentMatcher() {
        /** Required to get nice output */
        public void appendTo(StringBuffer buffer) {
            buffer.append("eqTwoString(" + twoString.getString1() + "," + twoString.getString2() + ")");
        }

        /** Implement equals basically */
        public boolean matches(Object object) {
            if (object instanceof TwoString) {
                TwoString other = (TwoString) object;
                // Consider adding null checks below
                return twoString.getString1().equals(object.getString1()) && twoString.getString2().equals(object.getString2());
            }
            else {
                return false;
            }
        }
    });
    return null;
}

다음과 같이 사용됩니다.

myInterfaceMock.callMe(eqTwoString(new TwoString("a","b")));

일부 세부 사항은 올바르지 않을 수도 있지만 본질적으로는 내가 전에 한 방식입니다. 또 다른 예와 더 철저한 설명이 있습니다 EasyMock 문서에서. 그냥 검색하십시오 IArgumentMatcher.

다른 팁

우선 - 모든 클래스가 약간 평등의 구현 (다른 것을 무시하지 않으면 객체에서 물려받은 것).

이 경우의 대답은 간단합니다. 모든 값 객체는 실제로 동등하고 해시 코드를 구현해야합니다. Twostring과 같은 단순한 사람이든, 당신이 암시하는 더 복잡한 대상이든, 그것이 다른 객체와 동등한 지 확인하는 것은 대상의 책임이어야합니다.

유일한 다른 대안은 기본적으로 테스트 코드에서 객체를 해체하는 것입니다.

assertEquals(expected, twoStr);

당신은 할 것입니다

assertEquals(expected.getStringOne(), twoStr.getStringOne());
assertEquals(expected.getStringTwo(), twoStr.getStringTwo());

바라건대 당신은 이것이 적어도 세 가지 방법으로 나쁘다는 것을 알 수 있기를 바랍니다. 첫째, 기본적으로 클래스 '자신의 equals () 메소드에 있어야하는 논리를 복제하고 있습니다. 그리고이 객체를 비교하려는 곳마다 동일한 코드를 작성해야합니다.

둘째, 대상의 공개 상태 만 볼 수 있습니다. 보기에 비슷한 객체가 동일하지 않아야합니다 (예 : 리프트 클래스는 공개적으로 액세스 할 수있는 "바닥"속성을 가질 수 있지만 개인 "상태로 올라가거나 아래로 내려갈 수 있습니다).

마지막으로, 타사 계급이 기본적으로 사물이 평등한지 여부를 해결하려고 노력하는 Twostring의 내부를 엉망으로 만드는 것은 Demeter의 법칙을 위반 한 것입니다.

객체 자체는 자체 equals () 메소드 - 순수하고 단순해야합니다.

Jakarta Commons Lang을 살펴보십시오. equalsbuilder.reflectionequals ()

내가 동의하는 동안 Dtsazza 모든 가치 객체에는 an이 있어야합니다 equals() (그리고 hashCode()) 방법, 테스트에 항상 적절한 것은 아닙니다. 대부분의 가치 객체는 모든 필드가 아닌 키에 평등을 기본으로합니다.

동시에, 나는 모든 필드를 확인하고 싶은 테스트를 거부합니다. "이 방법이 변경할 계획이 아닌 것을 바꾸지 않았는지 확인하는 것 같습니다." 이것은 유효한 테스트이며 어느 정도는 매우 선의의 테스트를 거치지 만, 필요하다고 느끼는 것은 약간 무섭습니다.

이 경우 TwoString 객체에는 매우 간단하며,그것은 쉬운 것입니다 equals 메서드를 재정의해야 합니다-하지만 무엇이 필요한 경우 확인하는 더 복잡한 객체입니다.

한 개체를 시작 되도록 복잡할 수 없는 손쉽게 확인하는 경우 그들은 동등한 다른 곳에서 당신은 아마 리팩터링과 주입으로 그들을 의미할 수 있습니다.이것은 디자인을 변경하지만,일반적으로는 더 나은입니다.

당신은 또한 것에 의존하는 일부의 지식을 내부 행동실 수 있습니다.위의 상호 작용을 테스트를 사이에 두 개의 클래스는 여전히 정상 작동하지만,더 큰 세트 테스트 구성 요소를 가져옵니다,당신이 덜 수 있습니다 정말 아직도에 대해 이야기"단위"테스트합니다.특정 시점에 당신을 떠나의 영역 단위 테스트와 당신이 시작을 통합,테스트하는 경우에 더 좋을 수 있습한 테스트를 활용하고 격리하는 행동을 특정 장소에서...

Mockito 1.8의 Argument Captors로이를 달성 할 수 있습니다.

http://mockito.googlecode.com/svn/branches/1.8.0/javadoc/org/mockito/mockito.html#15

나는 당신이 EasyMock을 사용하고 있다는 것을 알고 있지만 Mockito로 바꾸는 것은 쉽고 훨씬 좋습니다!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top