XUnit kullanarak bir İstisna Onaylayın


111

XUnit ve Moq için acemiyim. Bir argüman olarak string alan bir metodum var. XUnit kullanarak bir istisna nasıl işlenir.

[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException() {
    //arrange
    ProfileRepository profiles = new ProfileRepository();
    //act
    var result = profiles.GetSettingsForUserID("");
    //assert
    //The below statement is not working as expected.
    Assert.Throws<ArgumentException>(() => profiles.GetSettingsForUserID(""));
}

Test edilen yöntem

public IEnumerable<Setting> GetSettingsForUserID(string userid)
{            
    if (string.IsNullOrWhiteSpace(userid)) throw new ArgumentException("User Id Cannot be null");
    var s = profiles.Where(e => e.UserID == userid).SelectMany(e => e.Settings);
    return s;
}

1
"Beklendiği gibi çalışmıyor" derken neyi kastediyorsunuz? (Ayrıca, lütfen kodunuzu daha okunaklı bir şekilde biçimlendirin. Önizlemeyi kullanın ve okuyorsanız nasıl görünmesini istediğinizi görünce yayınlayın.)
Jon Skeet

4
İpucu: Aramaya GetSettingsForUserID("")başlamadan önce ararsınız Assert.Throws. Assert.ThrowsÇağrı sana yardım edemez. Ben ... AAA hakkında daha az sert olması öneririm
Jon Skeet

Yanıtlar:


184

Assert.Throws ifade istisna yakalamak ve türünü iddia olacaktır. Bununla birlikte, test edilen yöntemi assert ifadesinin dışında çağırıyorsunuz ve bu nedenle test olayında başarısız oluyorsunuz.

[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException()
{
    //arrange
    ProfileRepository profiles = new ProfileRepository();
    // act & assert
    Assert.Throws<ArgumentException>(() => profiles.GetSettingsForUserID(""));
}

AAA'ya göre eğilirseniz, eylemi kendi değişkenine çıkarabilirsiniz.

[Fact]
public void ProfileRepository_GetSettingsForUserIDWithInvalidArguments_ThrowsArgumentException()
{
    //arrange
    ProfileRepository profiles = new ProfileRepository();
    //act
    Action act = () => profiles.GetSettingsForUserID("");
    //assert
    var exception = Assert.Throws<ArgumentException>(act);
    //The thrown exception can be used for even more detailed assertions.
    Assert.Equal("expected error message here", exception.Message);
}

İstisnanın, mod ayrıntılı iddialar için de nasıl kullanılabileceğine dikkat edin


5
Zaman uyumsuz yöntemler kullanıyorsanız, Visual Studio yukarıdaki sözdizimiyle bir uyarı atar. Bunu tercih ediyor:async Task act() => await service.DoTheThingAsync(); await Assert.ThrowsAsync<InvalidOperationException>(act);
Alec

5
Aslında benim için bir hatayla sonuçlanan 'Task'ı dolaylı olarak Func <Task>' a dönüştüremiyorum ', oysa eğer sadece koyarsam Task act() => service.DoTheThingAsync(); await Assert.ThrowsAsync<InvalidOperationException>(act);bundan memnun olur ve iyi çalışır.
Alec

async / await ile çalışmak bunu nasıl etkiler? Bunu testimde ThrowsAsync kullanarak yapmaya çalıştığımda, hatayı başarıyla attığı ve testten çıktığı için Assert.Equal satırına asla ulaşmıyor. bunun yeni bir soru olup olmadığını görmek için suyu test etmek ...
nathanjw

@AlecDenholm Teşekkürler! Benim için işe yarayan tek şey bu. Diğer önerilerin bazılarının eşzamansız şeyler için gerçekten düzgün çalışmadığını düşünüyorum.
ticari marka

45

AAA konusunda katı olmak istiyorsanız, Act aşamanızdaki İstisnayı yakalamak için xUnit'ten Record.Exception'ı kullanabilirsiniz .

Daha sonra, Assert aşamasında yakalanan istisnaya göre iddialarda bulunabilirsiniz.

Bunun bir örneği xUnits testlerinde görülebilir .

[Fact]
public void Exception()
{
    Action testCode = () => { throw new InvalidOperationException(); };

    var ex = Record.Exception(testCode);

    Assert.NotNull(ex);
    Assert.IsType<InvalidOperationException>(ex);
}

Hangi yolu takip etmek istediğiniz size bağlıdır ve her iki yol da xUnit'in sağladığı şey tarafından tam olarak desteklenir.


1
FWIW, Bu çözüm, istisna mesajını vb. Doğrulamanız gerekiyorsa harika bir çözümdür. Sanırım o zaman Record.Exception'ı kullanabilirsiniz.
Jeff LaFay

@JeffLaFay Buradaki partiye biraz geç kaldığımı takdir ediyorum, bunun kullanmaktan var exception = Assert.Throws<InvalidOperationException>(testCode);ve ileri sürmekten ne farkı var exception.Message? yoksa aynı şeyi başarmanın başka bir çeşidi mi?
ColinM

3

AAA'ya bağlı kalmak istiyorsanız, buna benzer bir şey düşünebilirsiniz:

// Act 
Task act() => handler.Handle(request);

// Assert
await Assert.ThrowsAsync<MyExpectedException>(act);
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.