2015-08-07 5 views
9

У меня есть этот код:Как я могу издеваться этим статический методом

public static bool IsValidVoucher(string id) 
{ 
    //read tsv files 
    var temp1 = AppData.GetAppData("stringval");    
    // code that need to be tested   
    return true;   
} 

И я хотел бы создать модульное тестирование, но как я могу издеваться AppData.GetAppData("stringval") к тому, что я хочу, чтобы значение, так что я могу проверить остаток кода.

AppData класс:

public class AppData 
{ 
    public static object GetAppData(string name) 
    { 
     //... 
    } 
} 
+0

Вместо жесткого кодирования 'AppData.GetAppData' можно впрыснуть класс, который делает чтение AppData, а затем в вашем модульный тест, высмеивать этот класс и устанавливать требуемое значение возврата. – LInsoDeTeh

+0

С Moq невозможно без дальнейших изменений исходного кода. Но с помощью [Typemock's Isolator] (http://www.typemock.com/isolator-features/test-the-un-testable/fake-static-methods.html) это возможно. Однако Изолятор не свободен. – dee

+0

И [здесь] (http://adventuresdotnet.blogspot.de/2011/03/mocking-static-methods-for-unit-testing.html) дополнительную информацию о насмешливых статических методах. И [здесь] (http://stackoverflow.com/questions/5864076/mocking-static-methods) ответ от SO. HTH – dee

ответ

6

Статические методы не могут быть издевались легким способом. Вы в основном есть два варианта:

  1. Если у вас есть AppData класс, изменить реализацию для реализации интерфейса (например IAppData) и удалить модификатор static на методе GetAppData, так что вы можете дразнить его.

    public interface IAppData 
    { 
        object GetAppData(string id); 
    } 
    
    public class AppData : IAppData 
    { 
        public object GetAppData(string id) {} 
    } 
    
    public class Foo 
    { 
        private readonly IAppData _appData; 
    
        public Foo(IAppData appData) 
        { 
         _appData = appData; 
        } 
    
        public bool IsValidVoucher(string id) 
        { 
         // Call through object instance instead for class reference 
         var temp1 = _appData.GetAppData("stringval"); 
        } 
    } 
    
  2. Если вы не владеете AppData класс, использовать класс-оболочку (например, AppDataWrapper), который реализует интерфейс и вызвать этот метод из IsValidVoucher вместо:

    public interface IAppData 
    { 
        object GetAppData(string id); 
    } 
    
    public class AppDataWrapper : IAppData 
    { 
        public object GetAppData(string id) 
        { 
         return AppData.GetAppData(id); 
        } 
    } 
    
    public class Foo 
    { 
        private readonly IAppData _appData; 
    
        public Foo(IAppData appData) 
        { 
         _appData = appData; 
        } 
    
        public bool IsValidVoucher(string id) 
        { 
         var temp1 = _appData.GetAppData("stringval"); 
        } 
    } 
    

Вы можете затем единичный тест Foo с использованием Moq (в качестве примера здесь используется xunit):

public class FooTests 
{ 
    private readonly IAppData _mockAppData; 

    public FooTests() 
    { 
     var mockAppData = new Mock<IAppData>(); 
     mockAppData.Setup(m => m.GetAppData(It.IsAny<string>)).Returns("my test value"); 
     _mockAppData = mockAppData.Object; 
    } 

    [Fact] 
    public void IsValidVoucher_ValidAppData_Returns() 
    { 
     var foo = new Foo(_mockAppData); 
     // Unit test foo.IsValidVoucher 
    } 
} 
+0

Вы сказали, что статические методы не могут насмехаться ... См. Мой ответ: P Может быть, это сумасшедшая идея, но она работает! –

+0

@ MatíasFidemraizer, я должен сказать, что статический метод не может быть издеваемым ** простым способом **;) Отредактировано для ясности – rexcfnghk

+0

Я могу только сказать * lol * –

1

Ну, я думаю, что комментарии всех до сих пор технически правильны - используя что-то вроде RhinoMocks или Moq, вы действительно не можете издеваться над статическими методами простым, простым способом.

Но используя Moles, вы определенно можете. Поэтому, если у вас есть значительный (в настоящее время) непроверенный код, который находится в статических методах, я думаю, вы должны смотреть в Moles.

(Эта ссылка является немного устаревшим, но я до сих пор считаю полезным) http://research.microsoft.com/en-us/projects/pex/molesmanual.pdf

(Key текст)

Родинки могут быть использованы для объезда любой метод .NET, включая невиртуальные и статические методы в герметичных типах.

Как это работает: Предположим, у вас есть типичная ситуация, как это:

public static class SomeStaticClass 
{ 
    public static int SomeStaticMethod(string s) 
    { 
     return "Static method called: " + s; 
    } 
} 

public class SomeInstanceClass 
{ 
    public string SomeInstanceMethod(string s) 
    { 
     return SomeStaticClass.SomeStaticMethod(s); 
    } 
} 

Используя Родинки, ваш тестовый код будет выглядеть следующим образом:

[TestMethod()] 
[HostType("Moles")] 
public void ShouldBeAbleToTestStaticMethod() 
{ 
    var instance = new SomeInstanceClass(); 
    var testValue = instance.SomeInstanceMethod("Some test string"); 
    SomeStaticClass.SomeStaticMethod = (s) => "Moled you! " + s; 
    Assert.That(testValue, Is.EqualTo("Moled you! Some test string"); // sorry, this has code smell, lol 
} 

Конечно, вы должны установить вы сможете найти в своем тестовом проекте, поэтому обязательно просмотрите его - множество веб-ресурсов, которые помогут вам на вашем пути.

Некоторые полезные сообщения:

https://msdn.microsoft.com/en-us/library/ff798308.aspx

http://adventuresdotnet.blogspot.com/2011/03/mocking-static-methods-for-unit-testing.html

https://wannabeegeek.wordpress.com/2013/03/13/unit-testing-made-easy-with-moles-part-i/

+0

Я думаю, что вы должны хотя бы показать какой-то код в своем ответе, чтобы показать, как Моулс может помочь единичному тестированию статических методов вместо простого размещения ссылок на различные ресурсы. – rexcfnghk

+0

Хорошая точка, сделайте через час или около того. – code4life

+1

Молины все еще поддерживаются/доступны? Сайт, похоже, утверждает, что Fakes заменит его, и предполагаемая ссылка для скачивания направит меня только к списку, где нет Молса. Возможно, я, возможно, пропустил ссылку на скачивание? –