2015-01-26 15 views
6

Tôi đang viết một số kiểm thử đơn vị sử dụng khung tích hợp của Visual Studio. Tôi cần phải viết một số trường hợp thử nghiệm mà vượt qua khi một ngoại lệ thích hợp được ném. Vấn đề là các ngoại lệ mà tôi cần kiểm tra là các ngoại lệ bên trong được lồng trong một ngoại lệ chung hơn. Có một số giải pháp dễ dàng hay tôi cần để mở rộng toàn bộ chức năng. Tôi hiện đang sử dụng thuộc tính [ExpectedException], nhưng nó sẽ không hoạt động tốt trong một tình huống như vậy.Kiểm tra đơn vị cho các ngoại lệ bên trong

Tôi cũng tò mò điều gì sẽ xảy ra khi chúng tôi sử dụng [ExpectedException] trong khi chúng tôi cũng có một số logic khẳng định trong bản thân bài kiểm tra. Cả hai điều kiện được đánh giá (ngoại lệ đã được ném và tuyên bố Assert hóa ra là hợp lệ) hoặc kiểm tra vượt qua ngay sau khi ngoại lệ chính xác được ném?

+0

Không sử dụng thuộc tính 'ExpectedException' (kiểm tra có thể vượt qua vì một số giai đoạn sắp xếp ném cùng một ngoại lệ không phải là pha hành động); Sử dụng 'Assert.Throws ' –

+0

Không có phương thức 'Ném' trong khung công tác của VS. Đối với hầu hết các trường hợp, tôi sử dụng ngoại lệ tùy chỉnh để làm cho việc sử dụng thuộc tính đủ chính xác. – zhulien

Trả lời

7

Nếu khuôn khổ của bạn không hỗ trợ ném tùy chỉnh, bạn thường có hai lựa chọn:

  1. Thực hiện điều đó cho mình
  2. Thay đổi (hoặc mở rộng) khuôn khổ

Tôi sẽ bắt đầu với thứ hai dung dịch. Cân nhắc sử dụng thư viện FluentAssertions. Nó cho phép bạn làm điều gì đó như thế này:

Action deleteUser =() => usersRepository.Delete(new User { Id = null }); 

deleteUser 
    .ShouldThrow<UserNotFoundException>() 
    .WithInnerException<ArgumentNullException>() 
    .WithInnerMessage("User Id must have value"); 

Bạn vẫn sẽ sử dụng khung kiểm tra Visual Studio, chỉ cần bạn có thêm một thư viện, xác nhận thông thạo.

sự lựa chọn đầu tiên, mặt khác là làm việc nhiều hơn một chút vì nó thường là trường hợp với các giải pháp cuộn bằng tay:

try 
{ 
    usersRepository.Delete(new User { Id = null }); 
    Assert.Fail("Deleting user with null id should throw"); 
} 
catch (UserNotFoundException ue) 
{ 
    Assert.AreEqual(ue.InnerException.Message, "User Id must have value"); 
} 

Bạn thay ExpectedException thuộc tính với mã tùy chỉnh khẳng định dụ ngoại lệ thực tế. Như tôi đã nói, đó là công việc nhiều hơn nhưng làm các trick.

+0

Vâng, đó phải là nó. Tôi chỉ muốn tránh mở rộng chức năng hoặc sử dụng thư viện bên ngoài nhưng có vẻ như đây là giải pháp duy nhất có thể vào lúc này. Cảm ơn bạn. – zhulien

6

Không phải là một giải pháp tổng thể nhưng trong Nunit bạn có thể làm điều này loại

var ex = Assert.Throws<Exception>(() => thing.ThatThrows()); 
Assert.That(ex.InnerException, Is.TypeOf<BadException>()); 

Có lẽ bạn có thể trong khuôn khổ thử nghiệm của bạn?

+0

Giống như tôi đã nêu trong nhận xét cho câu hỏi, khung của VS không hỗ trợ phương thức Ném và theo như tôi biết, giải pháp duy nhất có thể cho ngoại lệ "bắt" là sử dụng thuộc tính. Có lẽ tôi nên thay đổi mã như để ném các ngoại lệ chi tiết thay vì các biến thể lồng nhau. – zhulien

1

Để kiểm tra đơn vị tôi hiện đang sử dụng FluentAssertions. Kể từ khi tôi đã học được nó tôi không bao giờ muốn khẳng định công cụ theo bất kỳ cách nào khác.

Đối với khẳng định trường hợp ngoại lệ nhìn vào bit này của documentation

Đặc biệt này phần

Action act =() => subject.Foo2("Hello"); 

act.ShouldThrow<InvalidOperationException>() 
    .WithInnerException<ArgumentException>() 
    .WithInnerMessage("whatever") 
1

đây là một câu hỏi cũ nhưng tôi muốn chia sẻ thực hiện riêng của tôi về ExpectedInnerExceptionAttribute với các bạn. có thể hữu ích cho ai đó

public class ExpectedInnerExceptionAttribute : ExpectedExceptionBaseAttribute 
{ 
    public ExpectedInnerExceptionAttribute(Type exceptionType) 
    { 
    this.ExceptionType = exceptionType; 
    } 

    public Type ExceptionType { get; private set; } 

    protected override void Verify(Exception ex) 
    { 
    if (ex != null && ex.InnerException != null 
      && ex.InnerException.GetType() == this.ExceptionType) 
     { 
     return; 
     } 

     throw ex; 
    } 
} 

Bạn cũng có thể mở rộng để kiểm tra thông báo ngoại lệ, v.v. bạn chỉ cần thêm logic của riêng mình trong phương thức Xác minh.

Các vấn đề liên quan