문제

지난 여름 저는 기본적인 ASP.NET/SQL Server CRUD 앱을 개발하고 있었는데, 단위 테스트가 요구 사항 중 하나였습니다.데이터베이스에 대해 테스트하려고 할 때 몇 가지 문제가 발생했습니다.내가 이해하는 바에 따르면 단위 테스트는 다음과 같아야 합니다.

  • 무국적
  • 서로 독립적
  • 동일한 결과로 반복 가능합니다.지속적인 변경 없음

데이터베이스를 개발할 때 이러한 요구 사항은 서로 상충되는 것 같습니다.예를 들어 삽입할 행이 아직 없는지 확인하지 않고는 Insert()를 테스트할 수 없으므로 먼저 Delete()를 호출해야 합니다.하지만 그들이 아직 거기에 없다면 어떻게 될까요?그런 다음 먼저 Exists() 함수를 호출해야 합니다.

내 최종 솔루션에는 매우 큰 설정 기능(으악!)과 먼저 실행되어 설정이 문제 없이 실행되었음을 나타내는 빈 테스트 케이스가 포함되었습니다.이는 무국적 상태를 유지하면서 테스트의 독립성을 희생하는 것입니다.

내가 찾은 또 다른 해결책은 함수 호출을 쉽게 롤백할 수 있는 트랜잭션으로 래핑하는 것입니다. Roy Osherove의 XtUnit.이 작업에는 또 다른 라이브러리, 또 다른 종속성이 포함되며 당면한 문제에 대한 솔루션이 너무 무거워 보입니다.

그렇다면 이러한 상황에 직면했을 때 SO 커뮤니티는 무엇을 했습니까?


tgmdbm이 말했습니다:

일반적으로 좋아하는 자동화 된 장치 테스트 프레임 워크를 사용하여 통합 테스트를 수행하므로 일부 사람들은 혼란 스럽지만 동일한 규칙을 따르지 않습니다.당신은 많은 클래스의 구체적인 구현을 포함 할 수 있습니다 (단위 테스트를 받았기 때문에).테스트 중입니다 콘크리트 클래스가 서로 및 데이터베이스와 상호 작용하는 방법.

그래서 내가 이것을 올바르게 읽었다면 실제로는 방법이 없습니다. 효과적으로 데이터 액세스 계층을 단위 테스트합니다.아니면 데이터 액세스 계층의 "단위 테스트"에 데이터베이스와의 실제 상호 작용과 관계없이 클래스에서 생성된 SQL/명령 테스트가 포함됩니까?

도움이 되었습니까?

해결책

테이블이 존재하고, 예상 열이 포함되어 있으며, 적절한 제약 조건이 있는지 확인하는 것 외에는 데이터베이스를 단위 테스트할 수 있는 실제 방법이 없습니다.그러나 그것은 일반적으로 실제로 할 가치가 없습니다.

당신은 일반적으로 그렇지 않습니다 단위 데이터베이스를 테스트합니다.일반적으로 데이터베이스를 관련시킵니다. 완성 테스트.

일반적으로 선호하는 자동화된 단위 테스트 프레임워크를 사용하여 통합 테스트를 수행하므로 일부 사람들은 혼란스러워하지만 동일한 규칙을 따르지 않습니다.많은 클래스의 구체적인 구현을 포함시킬 수 있습니다(단위 테스트를 거쳤기 때문입니다).구체적인 클래스가 서로 및 데이터베이스와 상호 작용하는 방식을 테스트하고 있습니다.

다른 팁

D단위

이 도구를 사용하여 지정된 시간에 데이터베이스 상태를 내보낸 다음 단위 테스트 시 테스트 시작 시 자동으로 이전 상태로 롤백할 수 있습니다.제가 일하는 곳에서는 꽤 자주 사용합니다.

단위 테스트에서 외부 종속성에 대한 일반적인 솔루션은 모의 개체, 즉 테스트 중인 실제 개체의 동작을 모방하는 라이브러리를 사용하는 것입니다.이는 항상 간단한 것은 아니며 때로는 약간의 독창성이 필요하지만 "자신만의 롤"을 원하지 않는 경우 .Net에 대한 몇 가지 좋은(프리웨어) 모의 라이브러리가 있습니다.즉시 두 가지가 떠오릅니다.

코뿔소 모의 평판이 꽤 좋은 곳이에요.

NMock 또 다른 것입니다.

사용할 수 있는 상업용 모의 라이브러리도 많이 있습니다.좋은 단위 테스트를 작성하는 것의 일부는 실제로 코드를 설계하는 것입니다. 예를 들어, 적합한 인터페이스를 사용하여 인터페이스의 "가짜" 버전을 구현함으로써 종속 개체를 "모의"할 수 있습니다. 테스트 목적으로 예측 가능한 방법입니다.

데이터베이스 모의에서 이는 처리할 단위 테스트를 위해 구성된 테이블, 행 또는 데이터 세트 개체를 반환하는 개체로 자신의 DB 액세스 계층을 "모의"하는 것을 의미합니다.

내가 일하는 곳에서는 일반적으로 처음부터 자체 모의 라이브러리를 만들지 만 그렇다고 꼭 그래야 한다는 의미는 아닙니다.

예, 데이터베이스에 액세스하는 리포지토리 및 서비스에 액세스하려면 코드를 리팩터링해야 하며 그런 다음 테스트 중인 개체가 데이터베이스에 닿지 않도록 해당 개체를 모의하거나 스텁할 수 있습니다.이는 데이터베이스 상태를 저장하고 모든 테스트 후에 재설정하는 것보다 훨씬 빠릅니다!

나는 강력히 추천한다 Moq 조롱 프레임워크로 사용하세요.저는 Rhino Mocks와 NMock을 사용했습니다.Moq는 매우 간단했고 다른 프레임워크에서 겪었던 모든 문제를 해결했습니다.

나는 동일한 질문을 받았으며 여기의 다른 답변자와 동일한 기본 결론에 도달했습니다.실제 DB 통신 계층에 대한 단위 테스트를 방해하지 마세요. 그러나 모델 기능을 단위 테스트하려면(데이터를 올바르게 가져오고 형식을 올바르게 지정하는지 등을 확인하기 위해) 일종의 더미 데이터 소스 및 설정 테스트를 사용하세요. 검색되는 데이터를 확인합니다.

나 역시 단위 테스트에 대한 기본적인 정의가 많은 웹 개발 활동에 적합하지 않다고 생각합니다.하지만 이 페이지에서는 좀 더 '고급' 단위 테스트 모델을 설명하고 다양한 상황에서 단위 테스트를 적용하기 위한 아이디어를 얻는 데 도움이 될 수 있습니다.

단위 테스트 패턴

나는 바로 이 상황에 사용했던 기술을 설명했다. 여기.

기본 아이디어는 DAL의 각 방법을 실행하여 결과를 확인하고, 각 테스트가 완료되면 롤백하여 데이터베이스를 정리하는 것입니다(정크/테스트 데이터 없음).

"훌륭하다"고 생각하지 못할 수 있는 유일한 문제는 일반적으로 전체 CRUD 테스트(단위 테스트 관점에서는 순수하지 않음)를 수행하지만 이 통합 테스트를 통해 실제 CRUD + 매핑 코드를 확인할 수 있다는 것입니다.이렇게 하면 문제가 발생하는 경우 응용 프로그램을 실행하기 전에 알 수 있습니다(빠르게 진행하려고 할 때 많은 작업을 절약할 수 있습니다).

당신이 해야 할 일은 스크립트에서 생성한 데이터베이스의 빈 복사본에서 테스트를 실행하는 것입니다.테스트를 실행한 다음 데이터를 분석하여 테스트 실행 후 데이터가 정확히 일치하는지 확인할 수 있습니다.그런 다음 데이터베이스는 일회용이므로 삭제하면 됩니다.이는 모두 자동화될 수 있으며 원자적 작업으로 간주될 수 있습니다.

데이터 계층과 데이터베이스를 함께 테스트하면 프로젝트 후반에 놀라움이 거의 없습니다.그러나 데이터베이스에 대한 테스트에는 문제가 있으며, 주요 테스트는 많은 테스트에서 공유 한 상태에 대해 테스트하는 것입니다.한 번의 테스트에서 데이터베이스에 라인을 삽입하면 다음 테스트에서도 해당 라인도 볼 수 있습니다.
필요한 것은 데이터베이스에 대한 변경 사항을 롤백하는 방법입니다.
그만큼 거래 범위 클래스는 매우 복잡한 트랜잭션을 처리 할 수있을 정도로 현명합니다. 테스트 통화에 따른 코드가 자체 로컬 거래에 저지르는 중첩 거래.다음은 테스트에 롤백 기능을 추가하는 것이 얼마나 쉬운 지 보여주는 간단한 코드입니다.

    [TestFixture]
    public class TrannsactionScopeTests
    {
        private TransactionScope trans = null;

        [SetUp]
        public void SetUp()
        {
            trans = new TransactionScope(TransactionScopeOption.Required);
        }

        [TearDown]
        public void TearDown()
        {
            trans.Dispose();
        }

        [Test]
        public void TestServicedSameTransaction()
        {
            MySimpleClass c = new MySimpleClass();
            long id = c.InsertCategoryStandard("whatever");
            long id2 = c.InsertCategoryStandard("whatever");
            Console.WriteLine("Got id of " + id);
            Console.WriteLine("Got id of " + id2);
            Assert.AreNotEqual(id, id2);
        }
    }

LINQ to SQL을 ORM으로 사용하는 경우 즉시 데이터베이스를 생성할 수 있습니다(단위 테스트에 사용된 계정에서 충분한 액세스 권한이 있는 경우).보다 http://www.aaron-powell.com/blog.aspx?id=1125

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