2012-04-13 27 views
6

Tôi đang sử dụng MSTest để chạy một số kiểm tra tự động đối với một DB 5.6.19 qua Trình kết nối MySQL và sử dụng EntityFramework 4.3.Nested TransactionScope không thành công trong các thử nghiệm

Tôi đang cố gắng sử dụng TransactionScope trong thư viện lớp truy cập DB để thực hiện khôi phục khi cần. Ngoài ra, trong mã thử nghiệm của tôi, tôi muốn sử dụng TransactionScope để đưa DB trở lại trạng thái đã biết trước mỗi thử nghiệm. Tôi sử dụng các phương pháp TestInitializeTestCleanup để thực hiện việc này. Những trông giống như vậy:

[TestInitialize()] 
public void MyTestInitialize() 
{ 
    testTransScope = new TransactionScope(TransactionScopeOption.RequiresNew); 
} 

[TestCleanup()] 
public void MyTestCleanup() 
{ 
    Transaction.Current.Rollback(); 
    testTransScope.Dispose(); 
} 

Dựa trên việc xây dựng các đối tượng TransactionScope có trong hàm khởi tạo, tôi tin rằng tôi nên nhận được một phạm vi giao dịch mới (có không phải là một "môi trường xung quanh" một hiện vì vậy tôi tin rằng Điều này ".RequiresNew" là không quan trọng về mặt kỹ thuật ở đây vì ".Required" sẽ tạo ra kết quả tương tự. Vì tôi không chỉ định một giá trị timeout, nó cung cấp cho tôi thời gian chờ mặc định, mà tôi hiểu là 60 giây. . thời gian kiểm tra cho tôi để chạy

tôi đã có một chức năng gọi là AddDessert(DessertBiz dessertBizObject) trông, một phần, một cái gì đó như thế này:

using (var transScope = new TransactionScope(TransactionScopeOption.Required)) 
{ 
    try 
    { 
     // ... 
     context.Desserts.Add(dessert); 
     context.SaveChanges(); 
     var dessertId = dessert.Id; 
     DoOtherDessertStuff(dessertId, dessertBizObject); 
     transScope.Complete(); 
    } 
    catch (InvalidOperationException ex) 
    { 
     Console.WriteLine(ex.ToString()); 
    } 
} 

Và chức năng này được gọi bằng một trong các thử nghiệm của tôi.

Vì tôi đã chỉ định TransactionScopeOption.Required ở đây, tôi hy vọng rằng nó sẽ sử dụng phạm vi giao dịch "môi trường xung quanh" được tạo bởi hàm MyTestInitialize.

thử nghiệm của tôi được bố trí để thực hiện chức năng này DoOtherDessertStuff thất bại và ném một ngoại lệ, vì vậy cuộc gọi đến transScope.Complete(); không xảy ra và rollback xảy ra tự động khi thoát khỏi using khối trong AddDessert chức năng. Vấn đề tôi có ở đây là vì nó sử dụng phạm vi giao dịch môi trường xung quanh được tạo ra trong hàm MyTestInitialize, các cuộc gọi thử nghiệm Assert của tôi không xảy ra vì cuộn ngược phạm vi giao dịch đã xảy ra - ít nhất đây là những gì tôi nghĩ đang xảy ra. Tôi đã xác minh rằng Transaction.Current.TransactionInformation.StatusTransactionStatus.Aborted, vì vậy tôi cảm thấy khá chắc chắn đây là những gì đang xảy ra.

Tuyệt vời, vì vậy tôi nghĩ rằng tôi sẽ thay đổi phương thức AddDesert tôi để trông giống hệt như trên ngoại trừ việc tôi sẽ lọt một phạm vi giao dịch thay vì sử dụng một môi trường xung quanh, một số dòng using tôi trông vẻ bề ngoài như thế này:

using (var transScope = new TransactionScope(TransactionScopeOption.RequiresNew)) 

Mục đích ở đây là tôi có thể lồng các phạm vi giao dịch này, cho phép khôi phục trong mã sản xuất của tôi xảy ra và sau đó vẫn kiểm tra số Assert s trong mã thử nghiệm của tôi.

Nhưng những gì tôi đang tìm kiếm là tôi nhận được lỗi sau:

System.IO.IOException: Không thể đọc dữ liệu từ kết nối giao thông: Một nỗ lực kết nối thất bại vì các bên kết nối không đúng cách phản ứng sau một khoảng thời gian hoặc kết nối được thiết lập không thành công do máy chủ được kết nối không phản hồi.

Ý tưởng?

+0

Hãy đăng stacktrace và mã nơi nó xảy ra. – usr

Trả lời

0

Câu hỏi rất hay. Khi bạn tham khảo datacontext bên trong testmethod của bạn sau khi rollback, nó sẽ không có sẵn. Bạn cần phải ngăn chặn điều đó. Bạn không cần phải chỉ định tùy chọn bắt buộc.Đây là tùy chọn mặc định.

Phương pháp thử:

[TestMethod()] 
    public void CreateTestCheckContextCorrectly() 
    { 
     MailJobController target = new MailJobController(); 

     target.AddDessert("dessert for Omer"); 
     //With suppress, even if you rollback ambient trans, suppress will ignore ambient trans. You need to reference new context, previous context from controller may be disposed. 
     using (var suppressscope = new TransactionScope(TransactionScopeOption.Suppress)) 
     { 
      var newdbcontextref = new DbEntities(); 

      int recordcount = newdbcontextref.StatusDefinitions.Where(x => x.Name == "dessert for Omer").Count(); 

      Assert.AreEqual(0, recordcount); 
     } 
    } 

điều khiển phương pháp:

public void AddDessert(string dessert) 
    { 
     using (var transScope = new TransactionScope()) 
     { 
      try 
      { 
       // ... 
       StatusDefinition statusDefinition = new StatusDefinition() {Name = dessert}; 
       db.StatusDefinitions.AddObject(statusDefinition); 
       db.SaveChanges(); 
       Console.WriteLine("object id:"+statusDefinition.StatusDefinitionId); 
       throw new Exception("hee hee"); 
       transScope.Complete(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.ToString()); 
      } 
     } 
    } 
Các vấn đề liên quan