Позвольте мне подробнее остановиться на ответе Шёрда. Проблема, с которой вы сталкиваетесь, связана с невозможностью доступа к типу MyUser
из тестовой сборки. Эта проблема легко решается с помощью InternalsVisibleTo
атрибута сборки.
Однако я бы порекомендовал переосмыслить ваш дизайн и избавиться от интерфейса IMyUser
, а вместо этого просто использовать класс MyUser
(который должен быть общедоступным). Обычно вы размещаете сервисы за интерфейсами, а не объектами. Есть ли веские причины для предоставления нескольких реализаций IMyUser
?
Посмотрите, насколько чище эта реализация:
public interface IData
{
MyUser GetUserById(int id);
}
public class UserLogic
{
private IData da;
public UserLogic(IData da)
{
this.da = da;
}
public MyUser GetMyUserById(int id)
{
return da.GetUserById(id);
}
}
internal class MyUser {
int Id { get; set; }
string Name { get; set; }
}
Существует другое решение, если вы настаиваете на наличии интерфейса IMyUser
и его внутренней реализации. Ваше существующее решение, если я правильно выведу содержание IData.GetUserById<T>
, будет выглядеть примерно так:
public class UserData : IData {
T GetUserById<T>(int id) where T : IMyUser, new(){
T returned = new T();
//fill in properties
returned.Name = "test";
return returned;
}
}
Приведенный выше код является небольшим нарушением SRP (предупреждение, PDF) и сочетает в себе две обязанности - извлечение объекта из постоянного хранилища и создание экземпляра объекта. Мало того, он также накладывает ответственность за создание интерфейса, что еще хуже.
Разделение этих обязанностей с использованием Abstract Factory и Внедрение зависимостей (PDF) приведет к намного более чистому дизайну, который не страдает от той же проблемы, что и раньше.
public interface IMyUserFactory {
IMyUser Create();
}
public interface IData
{
IMyUser GetUserById(int id);
}
internal MyUserFactory : IMyUserFactory {
public IMyUser Create() {return new MyUser();}
}
internal class UserData : IData {
IMyUserFactory m_factory;
public UserData(IMyUserFactory factory) {
m_factory = factory;
}
public IMyUser GetUserById(int id) {
IMyUser returned = m_factory.Create();
//fill in properties
returned.Name = "test";
return returned;
}
}
//and finally UserLogic class
public class UserLogic
{
private IData da;
public UserLogic(IData da)
{
this.da = da;
}
public IMyUser GetMyUserById(int id)
{
return da.GetUserById(id);
}
}
//The test then becomes trivial
[TestMethod]
public void Test() {
var data = new Mock<IData>();
data.Setup(d => d.GetUserById(1)).Returns(new Mock<IMyUser>().Object);
var logic = new UserLogic(data.Object);
var result = logic.GetMyUserById(1);
}