노력 지원 단위 테스트 충돌

c# effort entity-framework-6 unit-testing vstest

문제

나는이 프로젝트에서 몇 가지 테스트를 물려 받았다. 그들은 SQL 데이터베이스에 대해 실행할 때 작동하지만 천천히. 노력을 사용으로 전환하려고합니다.
.NET4.5, EF6.2, 노력 1.3.10.

내 단위 테스트에서 두 가지 가능성이있는 문제가있을 수 있습니다.

테스트를 병렬로 실행할지 여부는 중요하지 않습니다.

1) 한 번에 둘 이상을 실행하면

'Center.Shared.Person'유형이 둘 이상의 엔티티가 동일한 기본 키 값을 가지기 때문에 변경 저장 또는 수락에 실패했습니다. 명시 적으로 설정된 기본 키 값이 고유한지 확인하십시오. 데이터베이스에서 생성 된 기본 키가 데이터베이스와 Entity Framework 모델에서 올바르게 구성되었는지 확인합니다. Database First / Model First 구성에 Entity Designer를 사용하십시오. Code First 구성에 'HasDatabaseGeneratedOption "유창 API 또는'DatabaseGeneratedAttribute '사용 ---> System.InvalidOperationException :'Center.Shared.Person '유형이 둘 이상의 기본 엔터티 값을 갖고 있기 때문에 변경 저장 또는 수락에 실패했습니다. 명시 적으로 설정된 기본 키 값이 고유한지 확인 데이터베이스 생성 기본 키가 데이터베이스 및 Entity Framework 모델에서 올바르게 구성되었는지 확인하십시오. 데이터베이스 첫 번째 / 모델 첫 번째 구성에 Entity Designer 사용 'HasDatabaseGeneratedOption "유창 API 사용 코드 첫 번째 구성의 'DatabaseGeneratedAttribute'.

따라서 테스트가 제대로 분리되지 않은 것 같습니다.
코드를 살펴보면 CreateTransient가 호출 된 것을 볼 수 있지만, 충분히 일시적이지는 않습니다.

    public DbConnection CreateConnection(string nameOrConnectionString)
    {
        lock (_lock)
        {
            if (_connection == null)
            {
                _connection = Effort.DbConnectionFactory.CreateTransient();
            }

            return _connection;
        }
    }

TestInitialize 루틴에서 데이터베이스를 다시 시도합니다.

    [TestInitialize]
    public override void Initialize()
    {
        db.Database.Delete();
        db.Database.CreateIfNotExists();
        db.Database.Initialize(true);

이것은 매우 복잡 한 코드이므로 더 많은 코드를 게시해야 할 경우 토끼 구멍의 바닥에 도달하기까지 오랜 시간이 걸립니다. PoC를 만드는 것이 더 좋습니다.

2) 테스트를 독립적으로 실행하면 다른 문제가 발생합니다. 다시 말하지만, 이것들은 SQL에 대해서는 통과했지만 Effort에 대해서는 통과하지 못했습니다.

    [TestMethod]
    public void ClientAccessorTests_Find()
    {
        Client result;
        Client client = new Client()
        {
            Complete = false,
            HeadOfHousehold = true,
            PersonID = _person.PersonID
        };

        _accessor.Create(client, _accessor.DefaultConnectionContext);

        result = _accessor.Find(new object[] { client.ClientID }, _accessor.DefaultConnectionContext);

        Assert.IsNotNull(result);  // Fails with Assert.IsNotNull failed. 
    }

생성은 다음으로 구성됩니다.

    public virtual EntityType Create(EntityType entity, ConnectionContext connectionContext)
    {
        IsContextValid(connectionContext);
        if (entity == null) throw new ArgumentException("", "entity");

        using (var db = CreateDbContext<DbContextType>(connectionContext))
        {
            db.Set<EntityType>().Add(entity);
            db.SaveChanges();
        }

        return entity;
    }

찾기는 다음으로 구성됩니다.

    public virtual EntityType Find(object[] primaryKey, ConnectionContext connectionContext)
    {
        IsContextValid(connectionContext);
        if (primaryKey == null || primaryKey.Length == 0) throw new ArgumentException("", "primaryKey");

        using (var db = CreateDbContext<DbContextType>(connectionContext))
        {
            return db.Set<EntityType>().Find(primaryKey);
        }
    }

CreateDbContext를 호출하는 것을 알고 있지만, 동일한 ID를 가진 동일한 데이터베이스로 보일 수있는 한 코드로 추적합니다.

테스트를 격리시켜야하는 이유는 무엇입니까?
그리고 메모리 내 데이터베이스를 사용할 때 Find가 작동을 멈추게하는 이유에 대한 아이디어가 있습니까?

수락 된 답변

모든 것이 app.config 파일의 설정을 통해 연결되는 암시 적 접근 방식을 사용하려고했습니다.
그 접근법을 포기하고 데이터베이스 연결을 생성하고 명시 적으로 설정하면 더 나은 행운을 시작했습니다.

        System.Data.Common.DbConnection connection = new EffortProviderFactory("").CreateConnection("");
        _accessor = new ClientAccessor();
        _accessor.Connection = connection;
        db = new EntitiesDb(connection);

기본 접근자는 모든 DbConnection을 사용하는 한 DB의 사본을 매회 생성합니다. 그래서 접근자를 설정하고 여기 그것을 사용 :

        if (_connection == null) {   // this is the path for the application
            if (connectionContext == null) {
                ret = new T();
            } else {
                ret = (T)Activator.CreateInstance(typeof(T), new object[] { connectionContext });
            }
        } else {  // this is the path for unit tests.
            ret = (T)Activator.CreateInstance(typeof(T), new object[] { _connection });
        }

마지막으로, DbContext와 DbContext를 사용하는 생성자를 추가해야했습니다.

    public EntitiesDb(DbConnection connection) : base(connection) { }

이제 '찾기'가 작동하고 테스트가 서로 방해하지 않습니다.
다음 단계는이 모든 것을 기본 클래스로 푸시하는 것입니다.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.