Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a class testable

So I have a class called User. It has an internal constructor. I want to create a User object though so I can mock it like this:

public ISessionManagerInstance MockedSessionManager()
{
    var manager = new Mock<ISessionManagerInstance>();
    var company = new Chatham.Web.Business.Classes.Company(500, "", "", Enumerations.WebRelationshipInfo.NotSet, "", 0, 0, Data.Login.TeamOwnership.NotSet, 0, 0, false, null, false);
    manager.Setup(p => p.Company).Returns(company);

    Chatham.Web.Business.Classes.User displayUser = typeof(Chatham.Web.Business.Classes.User);
    displayUser.EntityID = 1786;
    manager.Setup(p => p.DisplayUser).Returns(displayUser);

    return manager.Object;
}

Now, Company has a constructor, so that's easy. But User has one that's only internal. Is there any way I can create a User and just set one int property on it so I can pass that object back on the mock?

like image 638
slandau Avatar asked Dec 09 '22 09:12

slandau


2 Answers

I can think of two possibilities:

create an IUser interface, have User implement it and create mocks against it. This is a very common practice in the world of .NET testing. All of your methods that use Users will mostly likely need to now accept IUser references.

Another possibility (which I don't recommend, but it's there) is to use the InternalsVisibleTo assembly attribute. Then the internals of your production assembly can be visible from your test assembly.

like image 175
Matt Greer Avatar answered Dec 26 '22 20:12

Matt Greer


One option would be to add your Unit Test Project as an "internal to" of your main project, this allows your unit test code access to things marked "internal" without allowing anyone else to do so. Its a simple thing to implement in the AssemblyInfo.cs file:

// main project AssemblyInfo.cs file 
[assembly: InternalsVisibleTo("YourProject.Tests")]
like image 40
Nate Avatar answered Dec 26 '22 18:12

Nate