Làm cách nào để kiểm tra “không có ngoại lệ nào xảy ra” trong bài kiểm tra đơn vị MSTest của tôi?


88

Tôi đang viết một bài kiểm tra đơn vị cho một phương thức này trả về "void". Tôi muốn có một trường hợp mà bài kiểm tra vượt qua khi không có ngoại lệ nào được ném ra. Làm cách nào để viết điều đó trong C #?

Assert.IsTrue(????)

(Tôi đoán đây là cách tôi nên kiểm tra, nhưng những gì đi vào "???")

Tôi hy vọng câu hỏi của tôi đủ rõ ràng.


Bạn đang sử dụng MSTest hay NUnit?
Matt Grande

2
Trong MSTest, các trường hợp ngoại lệ không được lựa chọn sẽ tự động khiến các thử nghiệm không thành công. Bạn có đang cố gắng giải thích các trường hợp ngoại lệ bị bắt không?
Phil

Bạn có thể tra cứu "try-catch for C #" và điều đó sẽ hướng dẫn bạn cách xử lý các ngoại lệ được ném hoặc không ném.
Foggzie 23/02/12

1
Nếu NUnit, hãy xem Assert.That (lambda) .Quảng cáo. Không có gì (Mặc dù tôi nghĩ điều đó đã thay đổi gần đây)
Matt Grande

Câu trả lời:


138

Bài kiểm tra đơn vị của bạn dù sao cũng sẽ thất bại nếu một ngoại lệ được đưa ra - bạn không cần phải đưa ra một xác nhận đặc biệt.

Đây là một trong số ít các tình huống mà bạn sẽ thấy các bài kiểm tra đơn vị không có xác nhận nào cả - bài kiểm tra sẽ hoàn toàn thất bại nếu một ngoại lệ được đưa ra.

Tuy nhiên, nếu bạn thực sự muốn viết một xác nhận cho điều này - có lẽ để có thể bắt được ngoại lệ và báo cáo "dự kiến ​​không có ngoại lệ nhưng đã nhận được điều này ...", bạn có thể làm điều này:

[Test]
public void TestNoExceptionIsThrownByMethodUnderTest()
{
    var myObject = new MyObject();

    try
    {
        myObject.MethodUnderTest();
    }
    catch (Exception ex)
    {
        Assert.Fail("Expected no exception, but got: " + ex.Message);
    }
}

(ở trên là một ví dụ cho NUnit, nhưng điều này cũng đúng cho MSTest)


Rõ ràng là bạn không nên đi và bắt những trường hợp ngoại lệ như vậy để điều này đúng.
Servy

7
Một bài kiểm tra sẽ chỉ thất bại nếu một ngoại lệ không được ghi nhận được đưa ra. Phụ thuộc vào mã trong trình xử lý ngoại lệ, các bài kiểm tra đơn vị có thể vượt qua.
mã ăn được

1
Nó hữu ích cho Ms Unittest, vì vậy không có phương thức Assert.DoesNotThrow (() trong Unittest.
Başar Kaya

25

Trong NUnit, bạn có thể sử dụng:

Assert.DoesNotThrow(<expression>); 

để khẳng định rằng mã của bạn không có ngoại lệ. Mặc dù thử nghiệm sẽ thất bại nếu một ngoại lệ được ném ra ngay cả khi không có Xác nhận xung quanh nó, giá trị của phương pháp này là sau đó bạn có thể phân biệt giữa các kỳ vọng chưa được đáp ứng và lỗi trong các thử nghiệm của mình và bạn có tùy chọn thêm thông báo tùy chỉnh sẽ được hiển thị trong đầu ra thử nghiệm của bạn. Một kết quả kiểm tra có từ ngữ tốt có thể giúp bạn xác định lỗi trong mã của bạn đã khiến kiểm tra không thành công.

Tôi nghĩ rằng việc thêm các bài kiểm tra để đảm bảo rằng mã của bạn không có ngoại lệ là hợp lệ; ví dụ, hãy tưởng tượng bạn đang xác thực đầu vào và cần chuyển đổi một chuỗi đến thành chuỗi dài. Có thể có những trường hợp chuỗi là null và điều này có thể chấp nhận được, vì vậy bạn muốn đảm bảo rằng việc chuyển đổi chuỗi không có ngoại lệ. Do đó, sẽ có mã để xử lý trường hợp này, và nếu bạn chưa viết một bài kiểm tra cho nó, bạn sẽ thiếu sự bao quát xung quanh một phần logic quan trọng.


1
DoesNotThrow rõ ràng là tốt đẹp. Nếu bạn đã quen với việc nhìn thấy Assert. * Trong một bài kiểm tra, bạn có thể nghĩ rằng anh chàng kia lười biếng và hay quên.
Matt Beckman

Có bất kỳ tương đương cho nó trong vstest hoặc mstest không?
Dan Csharpster

1
@DanCsharpster, tôi không nghĩ rằng có, ít nhất là trong MSTest - khi tôi đã cần chức năng này trong MSTest trong quá khứ, tôi đã thực hiện một cái gì đó như thế này: public class TestBase { //believe me, I don't like this anymore than you do. protected void AssertDoesNotThrow(Action action, string message) { try { action(); } catch (Exception) { Assert.Fail(message); } } }
Clarkeye

@Clarkeye, đó là một ý tưởng thú vị. Cảm ơn! Hy vọng rằng họ sẽ học cách sao chép NUnit tốt hơn, trong các phiên bản sau. Tôi cũng nghĩ về việc viết một bộ điều hợp giữa vstest và NUnit.
Dan Csharpster

@DanCsharpster, một điều bạn có thể muốn xem là các xác nhận trôi chảy, có hỗ trợ tốt cho ShouldThrow và ShouldNotThrow: github.com/dennisdoomen/fluentassertions/wiki#exceptions . Các tài liệu nói rằng nó tương thích với MSTest (mặc dù tôi chỉ sử dụng nó với XUnit và NUnit). Có thể không làm mọi thứ bạn muốn, nhưng bạn có thể kết hợp nó với các xác nhận MSTest.
Clarkeye

11

Đừng kiểm tra rằng điều gì đó không xảy ra . Nó giống như đảm bảo rằng mã không bị phá vỡ . Điều đó ngụ ý rằng, tất cả chúng ta đều cố gắng tạo ra mã không vi phạm, ít lỗi. Bạn muốn viết các bài kiểm tra cho điều đó? Tại sao chỉ một phương pháp? Bạn không muốn tất cả các phương pháp của bạn được kiểm tra mà chúng không có một số ngoại lệ ? Theo con đường đó, bạn sẽ kết thúc với một thử nghiệm bổ sung, giả, không xác nhận cho mọi phương pháp trong cơ sở mã của bạn. Nó không mang lại giá trị gì.

Tất nhiên, nếu yêu cầu của bạn là xác minh phương thức không bắt được ngoại lệ , bạn sẽ kiểm tra điều đó (hoặc đảo ngược nó một chút; kiểm tra xem nó không ném những gì nó được cho là bắt).

Tuy nhiên, phương pháp / thực hành chung vẫn còn nguyên vẹn - bạn không viết thử nghiệm cho một số yêu cầu giả tạo / mơ hồ nằm ngoài phạm vi của mã được thử nghiệm (và thử nghiệm "nó hoạt động" hoặc "không ném" thường là một ví dụ về như vậy - đặc biệt là trong kịch bản khi trách nhiệm của phương pháp được biết rõ).

Nói một cách đơn giản - hãy tập trung vào những gì mã của bạn phải làm và kiểm tra điều đó.


10
-1 Tôi có thể nghĩ về chức năng tích cực yêu cầu và ngoại lệ không được ném. Đối với một - phương thức có nhiệm vụ xử lý các ngoại lệ, ghi nhật ký chúng và thực hiện hành động - mà không ném thêm ngoại lệ. Bạn đưa ra một quan điểm tổng quát tốt - nhưng sau đó nói một cách tuyệt đối như thể nó luôn đúng.
Rob Levine

3
@RobLevine: Tôi hiểu ví dụ của bạn và nhận ra rằng bạn viết thử nghiệm trong những trường hợp như vậy. Tuy nhiên, như bạn đã nhận thấy, quan điểm của tôi thực sự là về thực hành chung hơn - có thể nói, kiểm tra những gì mã của bạn phải làm so với kiểm tra những gì mã của bạn không làm. Tôi đã diễn giải lại bài đăng của mình một chút, để ý kiến ​​của tôi rõ ràng hơn và gần với những gì tôi đã nghĩ. Cũng cho bạn cơ hội để xem xét lại phiếu bầu của mình. Cảm ơn vì đã làm rõ và xin lỗi vì phản hồi chậm trễ.
km

4
Đã xóa bỏ phiếu phản đối - Tôi sẽ không vui như vậy khi bỏ phiếu xuống lần sau!
Rob Levine

4
Trong dự án của chúng tôi, chúng tôi có lớp htmlvalidator, lớp này ném ra các ngoại lệ nếu html không hợp lệ. Ví dụ: khi người dùng nhập (sử dụng bảng điều khiển) javascript ở dạng kết hợp phong phú. Vì vậy, trong mã trường hợp của tôi, những gì mã của tôi làm là không ném ra ngoại lệ (cách tiếp cận danh sách trắng) và tôi cần phải kiểm tra điều đó.
Machet

1
Không đồng ý với câu trả lời này. Kiểm tra sự vắng mặt của một cái gì đó đôi khi theo một kịch bản nhất định có thể là một thử nghiệm hợp lệ.
bytedev

7

Lớp người trợ giúp này đã gãi ngứa cho tôi bằng MSTest. Có lẽ nó cũng có thể làm xước của bạn.

[TestMethod]
public void ScheduleItsIneligibilityJob_HasValid_CronSchedule()
{
    // Arrange
    var factory = new StdSchedulerFactory();
    IScheduler scheduler = factory.GetScheduler();

    // Assert
    AssertEx.NoExceptionThrown<FormatException>(() =>
        // Act
        _service.ScheduleJob(scheduler)
    );
}

public sealed class AssertEx
{
    public static void NoExceptionThrown<T>(Action a) where T:Exception
    {
        try
        {
            a();
        }
        catch (T)
        {
            Assert.Fail("Expected no {0} to be thrown", typeof(T).Name);
        }
    }
}

@Remco Beurskens - thêm một lệnh bắt chung {} vào cuối NoExceptionThrown <T> sẽ loại bỏ các lỗi khác, đây không phải là hệ quả của phương pháp. Đây không phải là một phương pháp mục đích chung để loại bỏ tất cả các Ngoại lệ. Nó dự định chỉ thất bại khi một ngoại lệ của loại IS đã biết được ném ra.
JJS

1
Cái này giờ đã quá cũ, nhưng Assertcó một bộ truy cập thuộc tính singleton, Thatmột bộ truy cập có thể sử dụng làm móc nối cho các phương thức mở rộng. Nó có thể gọn gàng hơn và dễ khám phá Assert.That.DoesNotThrow()hơn là có AssertEx.DoesNotThrow(). Đây chỉ là một ý kiến.
Richard Hauer

3

Tôi thích nhìn thấy một Assert.Whateverđiểm ở cuối mỗi bài kiểm tra, chỉ để nhất quán ... nếu không có một bài kiểm tra, tôi thực sự có thể chắc chắn là không có một bài kiểm tra ở đó?

Đối với tôi, điều này đơn giản như đặt Assert.IsTrue(true);

Tôi biết tôi đã không vô tình đặt mã đó vào đó, và do đó tôi nên đủ tự tin khi đọc lướt qua rằng điều này đúng như dự định.

    [TestMethod]
    public void ProjectRejectsGappedVersioningByDefault() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        Assert.Throws<ScriptProject.InvalidProjectFormatException>(() => {
            var sut = new ScriptProject(files);
        });

    }

    [TestMethod]
    public void ProjectAcceptsGappedVersionsExplicitly() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        var sut = new ScriptProject(files, true);

        Assert.IsTrue(true);   // Assert.Pass() would be nicer... build it in if you like

    }

Nó không giống nhau. Nếu mã của bạn ném, sẽ không có xác nhận nào được thực hiện và quá trình chạy thử nghiệm của bạn sẽ thất bại. Bạn muốn tham gia vào khuôn khổ thử nghiệm bằng cách xác nhận một điều kiện.
DvS

1

Bạn tôi, Tim đã nói với tôi về mong đợi . Tôi thực sự thích điều này b / c nó ngắn gọn hơn, ít mã hơn và rất rõ ràng rằng bạn đang kiểm tra một ngoại lệ.

[TestMethod()]
[ExpectedException(typeof(System.Exception))]
public void DivideTest()
{
    int numerator = 4;
    int denominator = 0;
    int actual = numerator / denominator;
}

Bạn có thể đọc thêm về nó ở đây: Sử dụng thuộc tính ngoại lệ mong đợi .


1
OP không yêu cầu một ngoại lệ.
Daniel A. White,

Tôi sẽ để câu trả lời này ở đây. Tôi đã tìm thấy câu hỏi này trong khi tìm kiếm trên google để tìm cách kiểm tra ngoại lệ và câu trả lời này tôi nghĩ cần phải có ở đây. OP đã trả lời câu hỏi của họ cách đây 7 năm. Ngay cả liên kết đến câu trả lời khác tôi nghĩ là hữu ích.
Jess

Tốt lắm Tim. 🤔
ruffin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.