[c#] NUnit으로 개인 메서드를 어떻게 테스트합니까?

NUnit을 올바르게 사용하는 방법이 궁금합니다. 먼저 메인 프로젝트를 참조로 사용하는 별도의 테스트 프로젝트를 만들었습니다. 그러나이 경우 개인 메서드를 테스트 할 수 없습니다. 내 생각 엔 테스트 코드를 메인 코드에 포함시켜야한다고 생각 했나?! -그게 올바른 방법이 아닌 것 같습니다. (나는 테스트가 포함 된 코드를 배송한다는 생각이 싫다.)

NUnit으로 개인 메서드를 어떻게 테스트합니까?



답변

일반적으로 단위 테스트는 클라이언트의 관점에서 결과가 정확하다면 구현이 중요하지 않다는 이론에 따라 클래스의 공용 인터페이스를 다룹니다.

따라서 NUnit은 비공개 멤버를 테스트하기위한 메커니즘을 제공하지 않습니다.


답변

단위 테스트의 초점이 공용 인터페이스 여야한다는 데 동의하지만 개인 메서드도 테스트하면 코드에 대해 훨씬 더 세분화 된 인상을받을 수 있습니다. MS 테스트 프레임 워크에서는 PrivateObject 및 PrivateType을 사용하여이를 허용하지만 NUnit은 그렇지 않습니다. 대신 내가하는 일은 :

private MethodInfo GetMethod(string methodName)
{
    if (string.IsNullOrWhiteSpace(methodName))
        Assert.Fail("methodName cannot be null or whitespace");

    var method = this.objectUnderTest.GetType()
        .GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);

    if (method == null)
        Assert.Fail(string.Format("{0} method not found", methodName));

    return method;
}

이 방법은 테스트 가능성을 위해 캡슐화를 손상시킬 필요가 없음을 의미합니다. 비공개 정적 메서드를 테스트하려면 BindingFlags를 수정해야합니다. 위의 예는 인스턴스 메서드에 대한 것입니다.


답변

단위 테스트를 작성하는 일반적인 패턴은 공용 메서드 만 테스트하는 것입니다.

테스트하려는 개인 메서드가 많이있는 경우 일반적으로 코드를 리팩터링해야한다는 신호입니다.

이러한 메서드를 현재 살고있는 클래스에서 공개하는 것은 잘못된 것입니다. 그것은 당신이 그 클래스가 갖기를 원하는 계약을 깨뜨릴 것입니다.

헬퍼 클래스로 이동하여 공개하는 것이 옳을 수 있습니다. 이 클래스는 API에 의해 노출되지 않을 수 있습니다.

이렇게하면 테스트 코드가 공개 코드와 혼합되지 않습니다.

비슷한 문제는 개인 클래스를 테스트하는 것입니다. 어셈블리에서 내 보내지 않는 클래스. 이 경우 InternalsVisibleTo 특성을 사용하여 테스트 코드 어셈블리를 프로덕션 코드 어셈블리의 친구로 명시 적으로 만들 수 있습니다.


답변

테스트중인 대상 어셈블리의 동반자 어셈블리로 테스트 어셈블리를 선언하여 프라이빗 메서드를 테스트 할 수 있습니다. 자세한 내용은 아래 링크를 참조하십시오.

http://msdn.microsoft.com/en-us/library/0tke9fxk.aspx

이것은 대부분 프로덕션 코드에서 테스트 코드를 분리하므로 유용 할 수 있습니다. 이 방법에 대한 필요성을 찾지 못했기 때문에이 방법을 직접 사용한 적이 없습니다. 코드가 어떻게 처리하는지보기 위해 테스트 환경에서 복제 할 수없는 극단적 인 테스트 케이스를 테스트하는 데 사용할 수 있다고 생각합니다.

그래도 말했듯이 개인 메서드를 테스트 할 필요는 없습니다. likley보다 더 작은 빌딩 블록으로 코드를 리팩터링하기를 원합니다. 리팩토링 할 때 도움이 될 수있는 한 가지 팁은 시스템이 관련된 도메인에 대해 생각하고이 도메인에 서식하는 ‘실제’개체에 대해 생각하는 것입니다. 시스템의 개체 / 클래스는 실제 개체와 직접 관련되어야하며 개체가 포함해야하는 정확한 동작을 격리하고 개체 책임을 제한 할 수 있습니다. 이것은 특정 메소드를 테스트 할 수 있도록하기보다는 논리적으로 리팩토링하고 있음을 의미합니다. 개체 동작을 테스트 할 수 있습니다.

여전히 내부 테스트의 필요성을 느낀다면 코드 한 조각에 집중하고 싶기 때문에 테스트에서 조롱을 고려할 수도 있습니다. 모킹은 객체 종속성을 주입하지만 주입 된 객체는 ‘실제’또는 프로덕션 객체가 아닙니다. 동작 오류를 쉽게 분리 할 수 ​​있도록 하드 코딩 된 동작이있는 더미 개체입니다. Rhino.Mocks는 기본적으로 개체를 작성하는 인기있는 무료 모의 프레임 워크입니다. TypeMock.NET (커뮤니티 에디션을 사용할 수있는 상용 제품)은 CLR 개체를 모의 할 수있는 더 강력한 프레임 워크입니다. 예를 들어 데이터베이스 앱을 테스트 할 때 SqlConnection / SqlCommand 및 Datatable 클래스를 모의하는 데 매우 유용합니다.

이 답변이 일반적으로 단위 테스트에 대해 알리고 단위 테스트에서 더 나은 결과를 얻는 데 도움이되는 더 많은 정보를 제공하기를 바랍니다.


답변

저는 개인 메서드를 테스트 할 수있는 기능을 선호합니다. xUnit이 시작되었을 때 코드가 작성된 후 기능을 테스트하기위한 것이 었습니다. 이 목적을 위해 인터페이스 테스트만으로 충분합니다.

단위 테스트는 테스트 중심 개발로 발전했습니다. 모든 방법을 테스트 할 수있는 기능은 해당 애플리케이션에 유용합니다.


답변

이 질문은 고급 단계에 있지만이 작업을 수행하는 방식을 공유 할 것이라고 생각했습니다.

기본적으로 모든 단위 테스트 클래스는 해당 어셈블리의 ‘기본값’아래에있는 ‘UnitTest’네임 스페이스에 테스트중인 어셈블리에 있습니다. 각 테스트 파일은 다음과 같이 래핑됩니다.

#if DEBUG

...test code...

#endif

블록, 그리고 그것은 모두 a) 릴리스에서 배포되지 않고 b) 후프 점프없이 internal/ Friend레벨 선언을 사용할 수 있음을 의미합니다 .

이것이 제공하는 다른 것은이 질문과 더 관련이있는 partial클래스 의 사용입니다. 클래스를 사용하여 개인 메서드를 테스트하기위한 프록시를 만들 수 있습니다. 예를 들어 정수 값을 반환하는 개인 메서드와 같은 것을 테스트하는 데 사용할 수 있습니다.

public partial class TheClassBeingTested
{
    private int TheMethodToBeTested() { return -1; }
}

어셈블리의 기본 클래스 및 테스트 클래스에서 :

#if DEBUG

using NUnit.Framework;

public partial class TheClassBeingTested
{
    internal int NUnit_TheMethodToBeTested()
    {
        return TheMethodToBeTested();
    }
}

[TestFixture]
public class ClassTests
{
    [Test]
    public void TestMethod()
    {
        var tc = new TheClassBeingTested();
        Assert.That(tc.NUnit_TheMethodToBeTested(), Is.EqualTo(-1));
    }
}

#endif

개발 중에이 메서드를 사용하지 않도록해야합니다.하지만 릴리스 빌드는 곧 부주의 한 호출을 표시 할 것입니다.


답변

단위 테스트의 주요 목표는 클래스의 공용 메서드를 테스트하는 것입니다. 이러한 공용 메서드는 해당 개인 메서드를 사용합니다. 단위 테스트는 공개적으로 사용 가능한 동작을 테스트합니다.