Используйте динамические объекты для возврата различных типов из метода
Мастер модульного тестирования Microsoft создает объекты Accessor, если вам нужно протестировать непубличное свойство из другого проекта. В своих модульных тестах я создаю вспомогательные функции, чтобы не повторять один и тот же код только в каждом методе модульного теста. В настоящее время у меня есть два теста, которые практически идентичны, за исключением того, что один принимает стандартный открытый объект, а другой - версию Accessor. Поскольку Accessor основан на стандартной версии, у меня должна быть одна функция.
Я предполагал, что смогу использовать Generics для выполнения простого броска. Но после публикации вопроса я обнаружил, что это было намного больше работы, включая необходимость обновления базовых объектов. Это было подтверждено, когда я спросил, существует ли какой-либо другой подход. Было предложено, чтобы динамические объекты могли работать. Я не знаком с динамическими объектами. Может ли кто-нибудь опубликовать пример, позволяющий мне иметь одну общую функцию и определять объект во время выполнения?
Вот две существующие функции:
// Common function to create a new test record with standard Account object
internal static Account CreateAccount(bool saveToDatabase)
{
DateTime created = DateTime.Now;
string createdBy = _testUserName;
Account account = new Account(created, createdBy);
account.Notes = Utilities.RandomString(1000);
if (saveToDatabase)
account.Create();
}
// Common function to create a new test record with Account_Accessor
internal static Account_Accessor CreateAccount(bool saveToDatabase)
{
DateTime created = DateTime.Now;
string createdBy = _testUserName;
Account_Accessor account = new Account_Accessor(created, createdBy);
account.Notes = Utilities.RandomString(1000);
if (saveToDatabase)
account.Create();
}
У меня есть две дюжины этих модульных тестов, а реальные объекты имеют в среднем 10 свойств, примеры которых я упростил здесь.
Вот код Accessor, который создает API модульного теста (опять же, я сократил его, чтобы упростить пример):
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.ObjectModel;
using System.Data;
namespace NameHere.Bll
{
[Shadowing("NameHere.Bll.Account")]
public class Account_Accessor : ProjectBase_Accessor<Account>
{
protected static PrivateType m_privateType;
public Account_Accessor(PrivateObject value);
[Shadowing(".ctor@2")]
public Account_Accessor(DateTime created, string createdBy);
[Shadowing("_notes")]
public string _notes { get; set; }
public static Account_Accessor AttachShadow(object value);
[Shadowing("Create@0")]
public override void Create();
}
}
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.ComponentModel;
using System.Linq.Expressions;
namespace NameHere.Bll
{
[Shadowing("NameHere.Bll.ProjectBase`1")]
public class ProjectBase_Accessor<T> : BaseShadow, INotifyPropertyChanged
{
protected static PrivateType m_privateType;
public ProjectBase_Accessor(PrivateObject value);
[Shadowing("Created")]
public DateTime Created { get; set; }
public static PrivateType ShadowedType { get; }
[Shadowing("add_PropertyChanged@1")]
public void add_PropertyChanged(PropertyChangedEventHandler value);
public static ProjectBase_Accessor<T> AttachShadow(object value);
[Shadowing("Create@0")]
public virtual void Create();
}
}
1 ответ
Вот моя первая попытка использования общей функции с использованием динамических объектов. Он возвращает либо Account, либо Account_Accessor, в зависимости от логического параметра useAccessor:
internal static dynamic CreateAccount(bool saveToDatabase, bool useAccessor)
{
DateTime created = DateTime.Now;
string createdBy = _testUserName;
dynamic account;
if (useAccessor)
account = new Account_Accessor(created, createdBy);
else
account = new Account(created, createdBy);
account.Notes = Utilities.RandomString(1000);
if (saveToDatabase)
account.Create();
}
Любые предложения или комментарии по этому подходу?