Moq를 사용하여 메소드 호출 확인


142

저는 C #에서 단위 테스트를 처음 접했고 Moq를 사용하는 법을 배우고 있습니다. 아래는 내가 테스트하려고하는 수업입니다.

class MyClass
{
    SomeClass someClass;
    public MyClass(SomeClass someClass)
    {
        this.someClass = someClass;     
    }

    public void MyMethod(string method)
    {
        method = "test"
        someClass.DoSomething(method);
    }   
}

class Someclass
{
    public DoSomething(string method)
    {
        // do something...
    }
}

아래는 내 TestClass입니다.

class MyClassTest
{
    [TestMethod()]
    public void MyMethodTest()
    {
        string action="test";
        Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();
        mockSomeClass.SetUp(a => a.DoSomething(action));
        MyClass myClass = new MyClass(mockSomeClass.Object);
        myClass.MyMethod(action);
        mockSomeClass.Verify(v => v.DoSomething(It.IsAny<string>()));
    }
}

다음과 같은 예외가 있습니다.

Expected invocation on the mock at least once, but was never performed
No setups configured.
No invocations performed..

"MyMethod"메소드가 호출되고 있는지 확인하고 싶습니다. 뭔가 빠졌습니까?


1
에 SomeClass대한 정의 가 없으면 컴파일 MyMethod(string)되지 않습니다.
— Platinum Azure

죄송합니다 .. 내 질문을 편집했습니다 ..
— user591410

1
올바른 길을 가고 있지만 게시 된 코드에 버그가 있습니다. 컴파일되지 않습니다-Someclass에서 케이싱, DoSomething에서 void 반환. 그런 다음 공개 액세스가 필요하며 DoSomething을 가상으로 만드십시오. 간단히 말해 프로덕션 코드에도 버그가있을 수 있습니다.
— TrueWill

답변 주셔서 감사합니다. 모의 메서드를 설정하는 동안 인수를 잘못 설정했습니다 ..
— user591410

"설정이 구성되지 않았습니다." 오해의 소지가 있습니다. 호출 될 메소드의 동작을 설정할 필요가 없습니다. 또한 테스트중인 메소드를 호출 한 후 "확인"메소드를 실행해야합니다 (따라서 괜찮습니다).
— Sielu

답변:


209

잘못된 방법을 확인 중입니다. Moq를 사용하려면 종속성 클래스에서 메소드를 설정 한 다음 선택적으로 확인해야합니다.

다음과 같은 작업을 수행해야합니다.

class MyClassTest
{
    [TestMethod]
    public void MyMethodTest()
    {
        string action = "test";
        Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();

        mockSomeClass.Setup(mock => mock.DoSomething());

        MyClass myClass = new MyClass(mockSomeClass.Object);
        myClass.MyMethod(action);

        // Explicitly verify each expectation...
        mockSomeClass.Verify(mock => mock.DoSomething(), Times.Once());

        // ...or verify everything.
        // mockSomeClass.VerifyAll();
    }
}

다시 말해, 당신은 MyClass#MyMethodcall을 확인하고 있으며 , SomeClass#DoSomething그 과정에서 클래스가 확실히 한 번 호출 합니다. Times인수는 필요하지 않습니다 . 나는 단지 그 가치를 보여주고 있었다.


죄송합니다. 올바른 방법으로 질문을 편집했습니다. 언급했듯이 먼저 설정을 시도한 다음 확인을 수행했습니다. 여전히 같은 예외가 있습니다.
— user591410

22
기대치를 설정하고 동일한 기대치를 명시 적으로 검증하는 것이 중복되지 않습니까? mockSomeClass.VerifyAll();동일한 결과를 얻지 못하고 더 건조합니까?
— Tim Long

14
그렇습니다. 그러나 일부 사람들은 명시적인 태도를 선호합니다.
— Platinum Azure

3
적어도 VerifyAll ()을 언급 해 주셔서 감사합니다. 일단 당신이 그것에 대해 생각하면 분명합니다. 나는 명백한 접근 방식을 사용했을 수도 있지만 모든 것을 사용할 때 훨씬 깨끗합니다. 둘 다 감사합니다.
— JGood

1
Mock비교할 때의 한 가지 단점은 NSubstitute매개 변수도 확인하려고 시도하고 확인이 실패하면 수행 된 호출을 보여 주지만 확인 표현식에 변수를 사용한 경우 정확히 예상 한 것은 표시하지 않는다는 것입니다. 값이 아닌 이름이므로 변수에 정확히 어떤 값이 있는지 확인하기 위해 디버그해야합니다. NSubstitute는 둘 다의 값과 다른 값을 보여줍니다.
— 그렌 가스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.