2013-09-12 4 views
1

Я начал получать издевательские фреймворки, потому что хочу написать некоторые модульные тесты для методов, которые (косвенно) что-то пишут в базу данных. Вот небольшой пример структуры классов:Объект базы данных Mock, который вызывается частным методом

class SomePersistenceClass 
{ 
    public void Persist(object value, string type) 
    { 
     if (type.Equals("Numeric")) 
     { 
      PersistNumeric((int)value); 
     } 
    } 

    private void PersistNumeric(int number) 
    { 
     //Some Calculations and Creation of DBObject 
     number++; 
     var dbObject = new DatabaseObject {DbObjectData = new DatabaseObjectData {Number = number, Creator = "John Doe"}}; 
     PersistImpl(dbObject); 
    } 

    private void PersistImpl(IDatabaseObject dbObject) 
    { 
     try 
     { 
      dbObject.Save(); 
     } 
     catch (Exception) 
     { 
      //ErrorHandling 
      throw; 
     } 
    } 
} 

interface IDatabaseObject 
{ 
    DatabaseObjectData DbObjectData { get; set; } 
    void Save(); 
} 

class DatabaseObject : IDatabaseObject 
{ 
    public DatabaseObjectData DbObjectData { get; set; } 

    public void Save() 
    { 
     //Save to Database; 
    } 
} 

class DatabaseObjectData 
{ 
    public int Number { get; set; } 
    public string Text { get; set; } 
    public string Creator { get; set; } 
} 

То, что я хочу сделать сейчас, это проверить общественность настойчиво метод. Проблема здесь в том, что мой DatabaseObject сохранит данные в базе данных. Было бы легко высмеять метод сохранения DatabaseObject, но я не уверен, что лучший способ вставить издеваемый объект (как вы можете видеть, у меня нет знаний о DatabaseObject в моем общедоступном методе) в PersistImpl метод. Один тысяча должен был вытащить создание DatabaseObject для общедоступного метода. Так что-то вроде этого:

public void Persist(object value, string type, IDatabaseObject dbObject) 
    { 
     if (type.Equals("Numeric")) 
     { 
      PersistNumeric((int)value, dbObject); 
     } 
    } 

    private void PersistNumeric(int number, IDatabaseObject dbObject) 
    { 
     //Some Calculations and Creation of DBObject 
     number++; 
     dbObject.DbObjectData.Number = number; 
     dbObject.DbObjectData.Creator = "John Doe"; 
     PersistImpl(dbObject); 
    } 

Но я очень недоволен этим soultion. Мне нужно было бы создать объект базы данных за пределами класса persistence.

Есть ли хороший способ решить такую ​​проблему? Я определенно должен удалить доступ к базе данных в своих модульных тестах.

+0

Почему бы просто не ввести макет IDatabaseObject в конструктор SomePersistenceClass? –

+0

Это то, о чем я сейчас думаю. Проблема в том, что я не могу использовать тот же DatabaseObject и просто заменять данные. Есть объекты базы данных, которые имеют состояния, поэтому мне нужен собственный DatabaseObject для каждого объекта, который я хочу сохранить. –

+0

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

ответ

1

Один из способов решить проблему является делегировать строительство DatabaseObject объектов заводского класса:

interface IDatabaseObjectFactory 
{ 
    IDatabaseObject Create(DatabaseObjectData data); 
} 

class DatabaseObjectFactory : IDatabaseObjectFactory 
{ 
    public IDatabaseObject Create(DatabaseObjectData data) 
    { 
     return new DatabaseObject {DbObjectData = data }; 
    } 
} 

class SomePersistenceClass 
{ 
    readonly IDatabaseObjectFactory _factory; 

    public SomePersistenceClass() 
    { 
     _factory = new DatabaseObjectFactory(); 
    } 

    public SomePersistenceClass(IDatabaseObjectFactory factory) 
    { 
     _factory = factory; 
    } 

    public void Persist(object value, string type) { /* ... */ } 
    private void PersistImpl(IDatabaseObject dbObject) { /* ... */ } 

    private void PersistNumeric(int number) 
    { 
     //Some Calculations and Creation of DBObject 
     number++; 
     var dbObject = _factory.Create(new DatabaseObjectData {Number = number, Creator = "John Doe"}); 
     PersistImpl(dbObject); 
    } 

} 

Теперь, если вы проверяете ваш класс, вы можете перейти в FakeDatabaseObjectFactory, который возвращает FakeDatabaseObject, что не будет обращаться к вашей базе данных.

(Тем не менее, я нахожу, как вы обрабатываете доступ к базе данных с классом DatabaseObject немного ... странно, но это еще одна тема).

+0

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

Смежные вопросы