MSTest birim testimde "istisna oluşmadığını" nasıl kontrol ederim?


89

Bu yöntem için "void" döndüren bir birim testi yazıyorum. Bir istisna atılmadığında testin geçtiği bir durum olmasını istiyorum. Bunu C # ile nasıl yazabilirim?

Assert.IsTrue(????)

(Benim tahminim bu şekilde kontrol etmem gerektiği, ancak "???" içinde ne var)

Umarım sorum yeterince açıktır.


MSTest veya NUnit kullanıyor musunuz?
Matt Grande

2
MSTest'te yakalanmamış istisnalar, testlerin otomatik olarak başarısız olmasına neden olur. Yakalanan istisnaları hesaba katmaya mı çalışıyorsunuz?
Phil

"Try-catch for C #" ifadesine bakabilirsiniz ve bu size atılan veya atılmayan istisnaları nasıl ele alacağınız konusunda talimat verecektir.
Foggzie

1
NUnit, Assert.That (lambda) .Throws.Nothing içine bakmak (Sanırım rağmen bu son zamanlarda değişti) ise
Matt Grande

Yanıtlar:


139

Bir istisna atılırsa birim testiniz yine de başarısız olacaktır - özel bir iddia koymanıza gerek yoktur.

Bu, hiçbir iddia içermeyen birim testlerini göreceğiniz birkaç senaryodan biridir - bir istisna ortaya çıkarsa test dolaylı olarak başarısız olacaktır.

Bununla birlikte, bunun için gerçekten bir iddia yazmak istediyseniz - belki istisnayı yakalayabilmek ve "istisna beklenmedi ama bunu anladım ..." raporunu bildirmek için, şunu yapabilirsiniz:

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

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

(yukarıdakiler NUnit için bir örnektir, ancak aynısı MSTest için de geçerlidir)


Açıkçası, bunun doğru olması için böyle istisnalar yakalamamalısınız.
Servy

7
Bir test yalnızca yakalanmamış bir istisna atılırsa başarısız olur. İstisna işleyicilerdeki koda bağlı olarak, birim testleri geçebilir.
ediblecode

1
Bayan Unittest için kullanışlıdır, bu nedenle Unittest'te Assert.DoesNotThrow (() yöntemi yoktur.
Başar Kaya

26

NUnit'te şunları kullanabilirsiniz:

Assert.DoesNotThrow(<expression>); 

kodunuzun bir istisna oluşturmadığını iddia etmek için. Etrafında Assert olmasa bile bir istisna atılırsa test başarısız olsa da, bu yaklaşımın değeri, daha sonra testlerinizdeki karşılanmamış beklentiler ve hataları ayırt edebilmeniz ve özel bir mesaj ekleme seçeneğiniz olmasıdır. test çıktınızda görüntülenecektir. İyi yazılmış bir test çıktısı, kodunuzda bir testin başarısız olmasına neden olan hataları bulmanıza yardımcı olabilir.

Kodunuzun istisnalar atmadığından emin olmak için testler eklemenin geçerli olduğunu düşünüyorum; örneğin, girişi doğruladığınızı ve gelen bir dizeyi uzun bir dizeye dönüştürmeniz gerektiğini düşünün. Dizenin boş olduğu durumlar olabilir ve bu kabul edilebilir, bu nedenle dize dönüşümünün bir istisna oluşturmamasını sağlamak istersiniz. Bu nedenle, bu olayı ele almak için bir kod olacaktır ve bunun için bir test yazmadıysanız, önemli bir mantık parçasının kapsamını kaçıracaksınız.


1
Açıkça DoesNotThrow güzel. Assert. * 'I bir testte görmeye alışkınsanız, diğer adamın tembel olduğunu ve unuttuğunu düşünebilirsiniz.
Matt Beckman

Bunun vstest veya mstest'te herhangi bir eşdeğeri var mı?
Dan Csharpster

1
@DanCsharpster, en azından MSTest'te olduğunu sanmıyorum - geçmişte 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); } } }
MSTest'te

@Clarkeye, bu ilginç bir fikir. Teşekkürler! NUnit'i gelecekteki sürümlerde daha iyi kopyalamayı öğreneceklerini umuyoruz. Ayrıca vstest ve NUnit arasında bir adaptör yazmayı da düşündüm.
Dan Csharpster

@DanCsharpster, bakmak isteyebileceğiniz bir şey, ShouldThrow ve ShouldNotThrow için güzel bir desteğe sahip olan akıcı iddialardır: github.com/dennisdoomen/fluentassertions/wiki#exceptions . Dokümanlar bunun MSTest ile uyumlu olduğunu söylüyor (bunu yalnızca XUnit ve NUnit ile kullanmama rağmen). İstediğiniz her şeyi yapmayabilir, ancak yine de MSTest iddialarıyla karıştırabilirsiniz.
Clarkeye

12

Bir şey olduğunu test etmeyin olmaz . Kodun kırılmayacağından emin olmak gibi . Bu bir tür ima edildi, hepimiz kırılmayan, hatasız kod için çalışıyoruz. Bunun için testler mi yazmak istiyorsunuz? Neden sadece bir yöntem? Tüm yöntemlerinizin bir istisna oluşturmayacak şekilde test edilmesini istemez misiniz? Bu yolu takip ederek, fazladan, kukla, iddiasız bir testle sonuçlanacaksınız , kod tabanınızdaki her yöntem için elde . Hiçbir değeri yoktur.

Elbette, gereksiniminiz doğrulama yöntemi ise istisnaları yakalar , O testi yapmak (ya bunu biraz ters; buna yakalama için ne gerekiyor atmaz testi olduğunu).

Bununla birlikte, genel yaklaşım / uygulamalar bozulmadan kalır - test edilen kodun kapsamı dışında kalan bazı yapay / belirsiz gereksinimler için testler yazmazsınız (ve "işe yaradığını" veya "atmadığını" test etmek genellikle böyle - özellikle yöntemin sorumluluklarının iyi bilindiği senaryoda).

Basitçe söylemek gerekirse, kodunuzun ne yapması gerektiğine odaklanın ve bunu test edin.


10
-1 Gerektiren ve istisnaların atılmaması gereken olumlu işlevsellik düşünebiliyorum. İşi istisnaları ele almak olan bir yöntem için, istisnayı daha ileri götürmeden bunları günlüğe kaydedin ve eyleme geçin. İyi bir genel noktaya değindiniz - ama sonra her zaman doğruymuş gibi mutlak bir şekilde konuşun .
Rob Levine

3
@RobLevine: Örneğinizi anlıyorum ve bu gibi durumlarda testler yazdığınızın farkındayım. Yine de fark ettiğiniz gibi, benim amacım aslında daha genel bir uygulama ile ilgiliydi - tabiri caizse, kodunuzun ne yapması gerektiğini test etmek yerine kodunuzun yapmadığını test etmek. Yazımı biraz değiştirdim, böylece düşüncem daha net ve aklımdakilere daha yakın olsun. Ayrıca oyunuzu yeniden gözden geçirme fırsatı verir. Açıklama için teşekkürler ve gecikmiş yanıt için özür dilerim.
km

4
olumsuz oy kaldırıldı - Bir dahaki sefere olumsuz oylama konusunda o kadar tetikte olmayacağım!
Rob Levine

4
Projemizde html geçerli değilse istisnalar atan htmlvalidator sınıfımız var. Örneğin, kullanıcı girişi (konsol kullanarak) zengin birleşik javascript. Yani benim durum kodumda kodumun yaptığı şey istisna atmamaktır (beyaz liste yaklaşımı) ve bunu test etmem gerekiyor.
Machet

1
Bu yanıta katılmıyorum. Bazen belirli bir senaryo altında bir şeyin yokluğunu test etmek geçerli bir test olabilir.
bytedev

7

Bu yardımcı sınıf, MSTest ile kaşıntımı kaşıdı. Belki seninkini de çizebilir.

[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 - NoExceptionThrown <T> 'nin sonuna genel bir yakalama {} eklemek, yöntemin amaçlanan bir sonucu olmayan diğer hataları bastırır. Bu, tüm İstisnaları bastırmak için genel amaçlı bir yöntem değildir. Yalnızca bilinen türden bir istisna atıldığında başarısız olması amaçlanmıştır.
JJS

1
Bu artık çok eskidir, ancak genişletme yöntemleri için kanca olarak kullanılabilen Assertbir tekli özellik erişimcisine sahiptir That. Sahip olmak Assert.That.DoesNotThrow()yerine , daha temiz ve daha keşfedilebilir olabilir AssertEx.DoesNotThrow(). Bu sadece bir görüş.
Richard Hauer

3

Görmeyi seviyorum Assert.WhateverHer testin sonunda , sadece tutarlılık için ... bir olmadan, orada olmaması gerektiğinden gerçekten emin olabilir miyim?

Benim için bu, koymak kadar basit Assert.IsTrue(true);

Ben biliyorum ben vermedi yanlışlıkla orada bu kodu koymak ve böylece ben amaçlandığı gibi bu olduğunu aracılığıyla hızlı bir yağsız az güvenen yeterli olmalı.

    [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

    }

Aynı şey değil. Kodunuz atarsa, hiçbir iddiaya çarpılmayacak ve test çalıştırmanız başarısız olacaktır. Bir koşul ileri sürerek test çerçevesine bağlanmak istiyorsunuz.
DvS

1

Arkadaşım Tim bana ExpectedException'dan bahsetti . Bu b / c'yi gerçekten seviyorum, daha kısa, daha az kod ve bir istisna için test ettiğiniz çok açık.

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

Bununla ilgili daha fazla bilgiyi burada okuyabilirsiniz: ExpectedException Öznitelik Kullanımı .


2
OP bir istisna istemiyor.
Daniel A. White

Bu cevabı burada bırakacağım. İstisnaları nasıl test edeceğimi google'da ararken bu soruyu buldum ve bu cevabın burada olması gerektiğini düşünüyorum. OP'nin sorusu 7 yıl önce cevaplandı. Bence diğer cevaba bağlantı bile yardımcı oluyor.
Jess

Aferin Tim. 🤔
ruffin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.