Модульное тестирование Взаимодействие методов в одном классе в C # - PullRequest
0 голосов
/ 03 марта 2012

У меня есть следующий код

public ClassToTest : IClassToTest
{
    private readonly DBRepository rep;

    public bool MethodA()
    {
        //Some logic
        var result=MethodB();
        //Do some logic against result;
    }
    public ResultType MethodB()
    {
        return Rep.GetResult();
    }
}

Если я хочу провести модульное тестирование MethodA , какова наилучшая практика для проверки взаимодействия между MethodA и MethodB ? Я имею в виду проверить MethodA , как тестирование MethodB путём проверки зависимости базы данных Rep , как MethodA имеет следующую реализацию

    public bool MethodA()
    {
        //Some logic
        var result=Rep.GetResult();
        //Do some logic against result;
    }

Но это не интуитивно понятно, проверяя логику в коде и метод теста. Я ищу решение, похожее на упомянутое здесь для Java.

модульное тестирование методов комплексного обслуживания

Но это не работает для C #.

Еще один вопрос: что, если MethodB является приватным, имеет ли это значение для стратегии юнит-тестирования?

Обновление: предпочитаю не менять структуру класса. например, не сделать MethodB виртуальным или переместить MethodB из класса в другой тест

Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 03 марта 2012

Вы не хотите проверять взаимодействие между MethodA и MethodB, вы хотите проверить, что MethodA вернет ожидаемый bool результат, учитывая некоторый контекст.

Тот факт, что MethodA вызывает MethodB, не относится к этому тесту;но факт, что в какой-то момент будет вызываться Rep.GetResult(), таков:

Как вы упомянули, вы можете высмеивать зависимость Rep, поэтому не имеет значения, является ли MethodB public или private.

  1. Смоделировать и ввести зависимость
  2. Вызвать MethodA
  3. Утвердить на результат
0 голосов
/ 03 марта 2012
[TestMethod]
public void MethodAReturnsTrueGivenSomeDataAndCondition()
{
IDBRepository mockRepo = new Mock<IDBRepository>(); //Create a mock of your repository call
ClassToTest subjectToTest = new ClassToTest(mockRepo.Object); //Inject the dependency

mockRepo.SetUp(r=>r.GetResult()).Returns(someSampleTestData); //You're setting up the object that might return you true to return when mock repo will be called, by default it returns the default or null usually

var result = subjectToTest.MethodA();
mockRepo.Verify(r=>r.GetResult(), Times.Once); //Make sure your repo method was called
Assert.IsTrue(result); 

}

Как-то так, используя Moq в качестве примера фреймворка.

0 голосов
/ 03 марта 2012

Вы хотите изолировать свои методы, которые вы тестируете, то есть вы хотите имитировать MethodB при тестировании MethodA, и наоборот.

Также существует парадигма тестирования для проверки контракта (или интерфейса) классов. В этой парадигме вы не будете беспокоиться о не публичных не виртуальных методах. Я стараюсь высмеивать столько, сколько могу.

Я рекомендую вам использовать фальшивый фреймворк (smug, rhino mocks, moq, easymock) Smug самый крутой, но он еще не закончен - я просто покажу вам код ниже (вот как это будет работать без насмешливый фреймворк вам в помощь).

public enum ResultType
{
  Ok,
  NotOk,
}

public abstract class DBRepository
{
  public abstract ResultType GetResult();
}

public class ClassToTest
{
  public DBRepository Rep { get; set; }

  public virtual bool MethodA()
  {
    //Some logic
    var result = MethodB();
    //Do some logic against result;

    return result == ResultType.Ok;
  }

  protected virtual ResultType MethodB()
  {
    return Rep.GetResult();
  }
}

public class DBRepositoryMock : DBRepository
{
  public ResultType FakeReturn { get; set; }
  public override ResultType GetResult()
  {
    return FakeReturn;
  }
}

public class ClassToTest_MethodA : ClassToTest
{
  public ResultType MethodB_FakeReturn { get; set; }

  protected override ResultType MethodB()
  {
    return MethodB_FakeReturn;
  }
}

// tests

[TestMethod]
public void Test1()
{
  ClassToTest mock = new ClassToTest_MethodA();
  (mock as ClassToTest_MethodA).MethodB_FakeReturn = ResultType.Ok;
  Assert.IsTrue(mock.MethodA());
}

// or using injection
[TestMethod]
public static void Test2()
{
  var obj = new ClassToTest();
  obj.Rep = new DBRepositoryMock { FakeReturn = ResultType.NotOk };
  Assert.IsFalse(obj.MethodA());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...