Moq: How to mock a class that is not visible?

I have the following simplified code that describes my problem:

public interface IMyUser
{
    int Id { get; set; }
    string Name { get; set; }
}

Used in the dataccess layer as follows:

public interface IData
{
    T GetUserById<T>(int id) where T : IMyUser, new();
}

The userlogic class is defined as follows:

public class UserLogic
{
    private IData da;

    public UserLogic(IData da)
    {
        this.da = da;
    }

    public IMyUser GetMyUserById(int id)
    {
        return da.GetUserById<MyUser>(id);
    }
}

User logic uses the MyUSer class , which is displayed only internally.

I want to use Moq to make fun of a call at the dataaccess level . But since I cannot access the MyUser class from my unit test code (which is also designed), I don’t know how to configure moq? A.

Moq code should look something like this:

var data = new Mock<IData>();
data.Setup(d => d.GetUserById<MyUser ???>(1)).Returns(???);

var logic = new UserLogic(data.Object);
var result = logic.GetMyUserById(1);

How to solve this?

+3
source share
3 answers

Sjoerd. , , 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) : . , , .

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);
}
+2

da.GetUserById<IMyUser>(id);

da.GetUserById<MyUser>(id);
+2

, testable, internal, [assembly: InternalsVisibleTo("MyAssemblyName")], MyAssemblyName - unit test , . , , .

+1

Source: https://habr.com/ru/post/1761918/


All Articles