Вы пытались просто вызвать этот метод и проверить ответ? Приятной особенностью фреймворков MVC является то, что вам не нужен весь фреймворк только для использования контроллера. Другие компоненты в стеке возьмут ActionResult и отобразят его в HTML.
PartialView возвращает PartialViewResult , свойство Model которого содержит модель, переданную в PartialView
.
Вы должны быть в состоянии написать модульный тест, который создает контроллер, вызывает действие и проверяет модель результата, например:
[Test]
public void viewPlayers_Returns_One()
{
var myController=new MyController(...);
var resultView=(PartialViewResult)myController.ViewPlayers("SomeName");
var players= (List<Player>)resultView.Model;
Assert.That(players, Has.Exactly(1).Items);
}
Mocking
Хитрая часть теперь вводит хранилище. Учитывая синтаксис, подобный LINQ, я предполагаю, что playerRepository
- это хранилище EF, внедренное через конструктор, или объект хранилища, который предоставляет сущности EF через свойство Players
.
Mocking EF показывается в нескольких SO вопросах и документации EF .
EF Core значительно облегчает имитацию с помощью провайдера базы данных в памяти . EF Core не привязан к среде выполнения .NET, что означает, что его можно использовать и в приложениях Full Framework. Тестирование с InMemory в документации содержит более подробный пример. Также есть пример, который показывает с использованием SQLite для более сложных сценариев
Будучи ленивым, я предполагаю, что репозиторий является классом, который реализует интерфейс:
public interface IPlayersRepository
{
public IQueryable<Player> Players {get;}
}
Легко создать фиктивный класс, который берет список, массив или игроков и выставляет их через Players
:
class MockPlayers
{
public IQueryable<Player> Players {get; private set;}
public MockPlayers(Player[] players)
{
Players=players.AsQueryable();
}
}
Это достаточно просто, чтобы даже не нуждаться в насмешливой структуре. После этого тест становится:
[Test]
public void viewPlayers_Returns_One()
{
var players=new[]{new Player{Name="SomeName"},new Player{Name="Other Name"}};
var mockRepo=new MockPlayers(players);
var myController=new MyController(mockRepo);
...
}
Moq будет полезен для более сложного интерфейса. Используя Moq, вы, вероятно, напишите:
var players = new[]{...};
var mockRepo=new Mock<IPlayersRepository>();
mockRepo.SetupGet(x => x.Players).Returns(players.AsQueryable());
EF Core
Если вы вводите контекст EF Core, например PlayersContext, вы можете настроить его для использования провайдера в памяти:
//setup
var options = new DbContextOptionsBuilder<PlayersContext>()
.UseInMemoryDatabase(databaseName: "Players Test")
.Options;
using(var ctx = new PlayersContext(options))
{
ctx.Players.Add(new Player{...});
ctx.SaveChanges();
}
//Execute
using(var ctx = new PlayersContext(options))
{
var myController=new MyController(ctx);
...
}
"Классик" EF
Все немного сложнее и требует дразнить DbSet и некоторые его методы. Адаптация сценария запроса документации будет выглядеть так:
//Setup
...
var data = players.AsQueryable();
var mockSet = new Mock<DbSet<Player>>();
mockSet.As<IQueryable<Player>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Player>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Player>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Player>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var mockContext = new Mock<PlayerContext>();
mockContext.Setup(c => c.Blogs).Returns(mockSet.Object);
//Execute
var myController=new MyController(mockContext.Object);
...
Я упоминал, что EF Core можно использовать в приложениях Full Framework?