Как я должен издеваться над этим простым методом сервисного уровня? - PullRequest
3 голосов
/ 10 февраля 2011

У меня есть следующий простой метод в моем слое службы.Я не уверен, как мне смоделировать различные цепочки частей, начиная с хранилища?

public ICollection<GameFile> FindAllActiveGamesFiles()
{
    return _gameFileRepository // <- this is an IRepository<GameFile>
        .Find() // <-- returns an IQueryable<T> .. in this case, an IQueryable<GameFile>
        .WhereIsActive() // <-- a simple Pipe/Filter; 'where x.IsActive'
        .ToList();
}

Я предпочитаю использовать Moq, но я очень рад видеть другие имплиментации .. в основном потому, чтоЯ не за точным синтаксическим ответом, а за теоретическим ответом.То есть.Вам нужно издеваться над IRepository<GameFile> и настраивать только метод ToList() .. бла-бла-бла ...

Это то, что я не понимаю, то, что я должен издеваться.Приветствия:)

--- Обновление: чтобы уточнить мой вопрос

Я пытаюсь проверить, что метод FindAllActiveGamesFiles () работает.Таким образом, я считаю, что мне нужно издеваться над gameFileRepository (который является интерфейсом).Я не уверен, что это ЕДИНСТВЕННАЯ вещь, которую я должен издеваться в этом примере.

например.

[TestMethod]
public void MyTest()
{
    // Arrange.
    Mock<IRepository<GameFile>> mockRepository = new Mock<IRepository<GameFile>>();
    mockRepository.Setup(....).MoreStuffToDo(...); // <-- that's what i'm unsure about.
    IGameFileService = new GameFileService(mockRepository, fakeLoggingService);

    // Act.
    var gameFiles = gameFileService.FindAllActiveGamesFiles();

    // Asserts.
    Assert.IsNotNull(gameFiles);
    CollectionAssert.AllItemsAreNotNull(gameFiles.ToArray());
    // .. and more asserts ///
    // What about expectations? eg. that ToList() was entered/called?
}

Ответы [ 2 ]

3 голосов
/ 12 февраля 2011

Похоже, вы хотите написать тест, который демонстрирует охват вашего заявления Linq.Вы уже указали, что ваш репозиторий является интерфейсом (IRepository ) и должен быть смоделирован.Вам просто нужно несколько примеров того, как продемонстрировать, что ваш сервисный уровень правильно фильтрует содержимое репозитория.

Вот ваш ServiceLayer, насколько я понимаю.

public class ServiceLayer
{
     private readonly IRepository<GameFile> _gameRepository;

     public SerivceLayer(IRepository<GameFile> repository)
     {
         _gameRepository = repository;
     }

     public IEnumerable<GameFile> FindAllActiveGamesFiles()
     {
         return _gameRepository
                    .Find()  // method we need to mock
                    .Where( gameFile => gameFile.IsActive)
                    .ToList();
     }
}

Давайте напишем несколько тестов .... (NUnit и Moq)

[TestFixture]
public class ServiceLayerFixture
{
      protected IRepository<GameFile> Repository;
      protected ServiceLayer Subject;
      protected ICollection<GameFile> Results;

      [Setup]
      public void Setup()
      {
          // create our mock
          Repository = new Mock<IRepository<GameFile>>().Object;

          // initialize our test subject
          Subject = new ServiceLayer(Repository);
      }

      [Test]
      public void WhenRepositoryDoesNotContainItems_ServiceLayer_ReturnsAnEmptyCollection()
      {
         Mock.Get(Repository)
             .Setup( r => r.Find())
             .Returns( new List<GameFile>().AsQueryable() );

         Results = Subject.FindAllActiveGameFiles();

         Assert.AreEqual(0, Results.Count);
      }

      [Test]
      public void WhenRepositoryDoesNotContainActiveItems_ServiceLayer_ReturnsAnEmptyCollection()
      {
         Mock.Get(Repository)
             .Setup( r => r.Find())
             .Returns( 
                 new List<GameFile>()
                     {
                        new GameFile { IsActive = false },
                        new GameFile { IsActive = false }
                     }.AsQueryable() );

         Results = Subject.FindAllActiveGameFiles();

         Assert.AreEqual(0, Results.Count);            
      }

      [Test]
      public void WhenRepositoryContainActiveItems_ServiceLayer_FiltersItemsAppropriately()
      {
         Mock.Get(Repository)
             .Setup( r => r.Find())
             .Returns( 
                 new List<GameFile>()
                     {
                        new GameFile { IsActive = true },
                        new GameFile { IsActive = false }
                     }.AsQueryable() );

         Results = Subject.FindAllActiveGameFiles();

         Assert.AreEqual(1, Results.Count);            
      }
}

Если ваш код останавливается, это то, что вы можете обрабатывать исключения из своего IRepository более изящно.

Так что рассмотрите:

[Test]
public void WhenTheRepositoryFails_ServiceLayer_ShouldHandleExceptionsGracefully()
{
    Mock.Get(Repository)
        .Setup( r => r.Find())
        .Throws( new InvalidOperationException() );

    Results = Subject.FindAllActiveGameFiles();

    Assert.AreEqual(0, Results.Count);          
}

Или, может быть, вы хотите обернуть исключение?

[Test]
[ExpectedException(typeof(GameFileNotFoundException))]
public void WhenTheRepositoryFails_ServiceLayer_ShouldReportCustomError()
{
    Mock.Get(Repository)
        .Setup( r => r.Find())
        .Throws( new InvalidOperationException() );

    Subject.FindAllActiveGameFiles();
}
0 голосов
/ 12 февраля 2011

Утверждая что-то о значении, возвращенном из ToList(), получается, что вы пытаетесь проверить фактические методы Find(), WhereIsActive() и ToList().Если это так, вам не нужно использовать фиктивные объекты.

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

Далее, для теста FindAllActiveGamesFiles() необходимо установить ожидания для mockRepository.Предполагая, что Find() и WhereIsActive() оба возвращают один и тот же репозиторий, вы будете устанавливать макет в качестве возвращаемого значения для этих методов.

Я не знаю API для вашей библиотеки-макета, но это такпосмотрите в psuedocode:

Mock<IRepository<GameFile>> mockRepository = new Mock<IRepository<GameFile>>();
List<GameFile> result = new List<GameFile>();
mockRepository.expect('Find')->willReturn(mockRepository);
mockRepository.expect('WhereIsActive')->willReturn(mockRepository);
mockRepository.expect('ToList')->willReturn(result);
IGameFileService service = new GameFileService(mockRepository, fakeLoggingService);

assertSame(service.FindAllActiveGamesFiles(), result);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...