Я использую MoQ в C # для выполнения модульных тестов / BDD-тестов, и мне часто нужно генерировать один и тот же объект дважды (потому что он потенциально будет использоваться в словаре). Или что-то на 99% то же самое, но только с другим идентификатором.
Есть ли способ «клонировать» определение Mock? Или создать два объекта с одинаковым определением?
2 ответа
Вы должны создать вспомогательный метод, который создает некоторые параметры для создания объекта Mock.
[Test]
public void MyTest()
{
Mock<ITestObject> myMock = CreateObject(1);
ITestObject obj = myMock.Object;
}
private Mock<ITestObject> CreateObject(int id)
{
Mock<ITestObject> mock = new Mock<ITestObject>();
mock.SetupGet(o => o.ID).Returns(id);
return mock;
}
private interface ITestObject
{
int ID { get; set; }
}
Если вам просто нужен набор данных для модульного тестирования, вы можете рассмотреть что-то вроде AutoFixture. Он может работать с Moq в случае классов, которые вы хотите смоделировать. Вы учите AutoFixture, как создавать YourClass, и вы даже можете устанавливать правила, такие как «мои идентификаторы должны быть строками с заглавными буквами и не более X раз их».
Тогда вы просто используете автокрепление.
var fixture = new Fixture();
var tetsClasses = fixture.CreateMany<TestClass>();
Это действительно просто, чтобы дать вам идею. Вы можете сделать с ним гораздо больше, и он хорошо играет с Moq.
Альтернативой является использование шаблона построителя данных для создания ваших данных. Таким образом, вы могли бы начать с чего-то простого и просто добавить к нему, когда вы найдете новые крайние примеры того, как вам нужно строить данные. Просто создайте свободный API и создайте данные так, как вы хотите.
internal class TestClassBuilder<T> : where T : TestClass
{
int Id {get; set;}
public T WithId(int id)
{
this.Id = id;
return this;
}
public virtual T Build()
{
return new T()
{
if(this.Id)
Id = this.Id; // if you chose to set it, then assign it
else
Id = GetRandomId() // you can figure a solution here
}
}
}
Тогда назовите это как:
var stubOne = TestClassBuilder.WithId(1).Build();
Вы можете расширить его, чтобы создать список, если хотите.
Мне нравятся свободно распространяемые API на сборщиках данных, потому что вы можете начать рассказывать свою историю с помощью методов, которые вы создаете, и она поддерживает раздел Arrange в чистоте и порядке. Пример:
var UnderAgeCustomer = new CustomerBuilder
.UnderAge
.WithFakeId
.InACrowd
.LooksYoung
.Build()
Вы могли бы даже добавить на
public static implicit operator T(TestClassBuilder<T> builder)
{
return builder.Build();
}
И вам не нужно будет постоянно использовать часть .Build () (я думаю, что сборка добавляет ненужный шум). Только не пытайтесь присвоить это переменной, это не сработает.
TestClass MockTwo = TestClassBuilder.WithId(2);
Я бы сказал, что вы также можете использовать шаблон фиксации для отслеживания всего этого ... но между этим и сборщиком данных вы также можете использовать AutoFixture и Moq, как я и предлагал :)
Новые вопросы
c#
C # (произносится как «резкий») - это высокоуровневый, статически типизированный язык программирования с несколькими парадигмами, разработанный Microsoft. Код C # обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, включая, среди прочего, .NET Framework, .NET Core и Xamarin. Используйте этот тег для вопросов о коде, написанном на C # или в формальной спецификации C #.