I'm trying to actually test my code for once, but mocking has always been (one of) my Achilles Heel(s).
I'm doing some stuff with AD, and want to test without actually touch it. Here's what I'm doing:
var userPrincipalMock = new Mock<UserPrincipal>();
userPrincipalMock.Setup(x => x.SamAccountName).Returns("somesamaccountname");
userPrincipalMock.Setup(x => x.EmployeeId).Returns("anemployeenumber");
But apparently UserPrincipal doesn't wanna give up control of a samaccount name that easily:
Message "Unsupported expression: x => x.SamAccountName\nNon-overridable members (here: Principal.get_SamAccountName) may not be used in setup / verification expressions."
Any of you lovely guys or gals know the right way to go about this?
It is impossible to test methods that aren't marked as virtual. For this reason only interfaces should be mocked. To solve your problem, you can create a wrapper:
interface IUserPrincipalWrapper
{
string SamAccountName { get; set; }
string EmployeeId { get; set; }
void Delete();
... // Add all methods and properties of UserPrincipal that you need
}
class UserPrincipalWrapper : IUserPrincipalWrapper
{
private UserPrincipal Implementation { get; }
UserPrincipalWrapper(UserPrincipal implementation)
{
Implementation = implementation;
}
public string SamAccountName
{
get => Implementation.SamAccountName;
set => Implementation.SamAccountName = value;
}
public string EmployeeId
{
get => Implementation.EmployeeId;
set => Implementation.EmployeeId = value;
}
public void Delete()
{
Implementation.Delete();
}
...
// Call or set everything to Implementation...
// This is needed to create an interface around UserPrincipal, which you can mock
}
// Factory is needed for mocking `new` calls..
// as often times, you don't want to test that either
interface IUserPrincipalFactory
{
IUserPrincipalWrapper Create(PrincipalContext context);
}
class UserPrincipalFactory : IUserPrincipalFactory
{
public IUserPrincipalWrapper Create(PrincipalContext context)
{
var implementation = new UserPrincipal(context);
return new UserPrincipalWrapper(implementation);
}
}
Then in your tests you can mock everything:
// This is your mock
var userPrincipalMock = new Mock<IUserPrincipalWrapper>();
// You need factory for mocking `new UserPrincipal();` calls
var factoryMock = new Mock<IUserPrincipalWrapperFactory>();
factoryMock.Setup(factory => factory.Create(It.IsAny<PrincipalContext>())).Returns(userPrincipalMock.Object);
// Now it works :)
userPrincipalMock.Setup(x => x.SamAccountName).Returns("somesamaccountname");
userPrincipalMock.Setup(x => x.EmployeeId).Returns("anemployeenumber");
Related
public class Details
{
public int Id { get; internal set; }
public string Name { get; set; }
}
I have a task where a setter in a model has an internal attribute and I have tried adding stuff like
[assembly: InternalsVisibleTo("sometestrepo")]
over the model class but to no avail. I googled for a couple of hours and I can't seem to find an answer. Is it even possible to xunit test it or mock and object so that it would allow to create an object with an Id. Otherwise how else am I supposed to fully test CRUD methods that are all based around ID parameter?
The solution is to make private members that you want to test internal.
then you can add InternalsVisibleTo attribute.
[assembly: InternalsVisibleTo("sometestrepo")]
if you're using Moq,You can use something like that:-
var mockAddress = new Mock<Details>();
mockAddress.SetupGet(p => p.Id).Returns(42);
mockAddress.SetupGet(p => p.Name).Returns("Whatever you want to match");
var mockAddressRepository = new Mock<IRepository<Details>>();
var addresses = new List<Details> { mockAddress.Object };
mockAddressRepository.Setup(p => p.GetEnumerator()).Returns(addresses.GetEnumerator());
var addressToMatch = mockAddressRepository.Object.FirstOrDefault(address => address.Id == 42);
Console.WriteLine(addressToMatch.Name);
Expected Output Is:-
Whatever you want to match
One solution that might work is to use a fake.
In your Test class create a fake Details class, inheriting from Details. Then you could new up the property.
public class FakeDetails : Details
{
public new int Id { get; set; }
}
You could use the fake in your test then to set the properties.
var fakeDetails = new FakeDetails();
fakeDetails.Id = 15;
fakeDetails.Name = "Some Name";
Imagine I have this class:
public class MyClass
{
public string Id { get; set; }
public string Name { get; set; }
public IList<MyOtherClass> MyOtherClassList { get; set; }
}
And this method on my service layer which I want to unit-test with Moq and xunit:
public IList<MyClass> GetAll()
{
var options = new FindOptions<MyClass>
{
Projection = Builders<MyClass>.Projection
.Exclude(m => m.MyOtherClassList)
};
return MyClassRepository.GetAll(options)
}
And this would be the test:
[Fact]
public void GetAll_Success()
{
//Arrange
List<MyClass> expected = ... ;
var mockMyClassRepository = new Mock<IMyClassRepository>();
mockMyClassRepository.Setup(m => m.GetAll(It.IsAny<FindOptions<MyClass>>())).Returns(expected);
var myClassService = new MyClassService(mockMyClassRepository);
//Act
var result = myClassService.GetAll();
//Assert
Assert.Equal(expected, result);
mockMyClassRepository.Verify(m => m.GetAll(It.IsAny<FindOptions<MyClass>>()), Times.Once);
}
I want to avoid using It.IsAny for the FindOptions and be sure that the findOptions are excluding the MyOtherClassList attribute but I'm not sure how to compare the FindOptions class.
Any suggestion?
Hows this
mockMyClassRepository
.Setup(m => m.GetAll(It.IsAny<FindOptions<MyClass>>()))
.Returns(FindOptions<MyClass> a) =>
{
if (a.MyOtherClass != null || a.MyOtherClass.Length() > 0)
throw new InvalidOperationException();
else
return expected;
});
You can use an expression in the Returns to inspect the provided argument so you can apply what ever filtering you want.
mockMyClassRepository
.Setup(_ => _.GetAll(It.IsAny<FindOptions<MyClass>>()))
.Returns((FindOptions<MyClass> options) => {
var projection = options.Projection;
//...use as desired to filter the expected.
return expected;
});
The same could have been done in a Callback where the expected could be manipulated/altered, again based on the passed argument.
Do note that what ever is done with the passed argument is an implementation concern that applies to what is done by the actual repository, which you are trying to mock.
The only way to be sure that the findOptions are actually excluding the MyOtherClassList attribute would be via an integration test.
If you're looking to be more specific on the .Verify call, you can leave the .Setup call to use It.IsAny, then use additional constrains on the verify call, like this:
mockMyClassRepository.Verify(m => m.GetAll(It.Is<FindOptions<MyClass>>(options =>
options.Projection == .... //whatever logic would return true for your success criteria
)), Times.Once);
I'm trying to achieve maybe something that might be impossible.
We have a big MVC 5 application. I created a small MVC project to simulate and explain what I want to apply into that big MVC project.
I have a controller that has unique Id. In this sample project the unique Id is regenerated for each request. In the MVC project, it is a bit more complex and different. However it's not relevant in the scope of this example.
public class FooController : Controller
{
public string UniqueId = Guid.NewGuid().ToString("N");
public ActionResult Index()
{
var worker = new WorkerA();
worker.DoWork();
return View();
}
}
The FooController creates WorkerA which creates WorkerB which creates WorkerC and so on. The workers are not the same. They don't have the same interface/implementation. To make the example simple I made them look similar.
Here's the Workers:
public class WorkerA
{
public string UniqueId = string.Empty;
public void DoWork()
{
var worker = new WorkerB();
worker.DoWork();
//...
//...
}
}
public class WorkerB
{
public string UniqueId = string.Empty;
public void DoWork()
{
var worker = new WorkerC();
worker.DoWork();
}
}
I want to have inject the property UniqueId into the worker without having to passing it as a parameter.
I want to avoid having to do this:
public WorkerA(string uniqueId)
{
UniqueId = uniqueId;
}
But I need to do the same for all the other workers.
EDIT
Is there a way to acheive that with ninject?
You can achieve what you want using Microsoft.Practices.Unity in the following manner:
public class WorkerA
{
[Dependency]
public string UniqueId { get; set; }
}
public class WorkerB
{
[Dependency]
public string UniqueId { get; set; }
}
And after that :
var container = new UnityContainer();
container.RegisterType<WorkerA>(new InjectionProperty(nameof(WorkerA.UniqueId),"WorkerAValue"));
container.RegisterType<WorkerA>(new InjectionProperty(nameof(WorkerB.UniqueId), "WorkerBValue"));
Later, you can request the instances from the container with the desired properties configured:
var workerA = container.Resolve<WorkerA>();
var workerB = container.Resolve<WorkerB>();
You can do something like:
worker.GetType().GetField("prop")?.SetValue(worker, "guid");
You could create a singleton class to manage the GUID and deliver it to the child classes that way. This way you can still do it in a constructor but not have to pass it as a parameter
public class GUIDManager
{
private static GUIDManager _instance;
private Guid _activeGuid;
public Guid ActiveGuid {
get { return _activeGuid; }
set { _activeGuid = value; }
}
private GUIDManager()
{
if (_activeGuid == null)
_activeGuid = new Guid();
}
public static GUIDManager GetInstance()
{
if(_instance == null)
{
_instance = new GUIDManager();
}
return _instance;
}
}
public class WorkerB
{
public string UniqueId = string.Empty;
public WorkerB()
{
var manager = GUIDManager.GetInstance();
UniqueId = manager.ActiveGuid.ToString();
}
public void DoWork()
{
var worker = new WorkerC();
worker.DoWork();
}
}
From your question i'm not entirely clear about all the workers in the same request getting the same ID or not. If they all should get the same ID then it's simple:
Wrap the ID in a class and use InRequestScope():
public class BrowserTabId
{
public string browserTabId;
public BrowserTabId(string tabId)
{
if(string.IsNullOrEmpty(tabId))
{
throw new NullArgumentException();
}
this.browserTabId = tabId;
}
public string Id { get { return this.browserTabId; } }
}
Bind<BrowserTabId>()
.ToMethod(ctx =>
new BrowserTabId(HttpContext.Items["BrowserTabId"] as string)))
.InRequestScope();
For testability reasons you can also slap on an interface IUniqueRequestId and create the binding for that.
This will result in all workers / objects created during the same request receiveing the same BrowserTabId. If you don't want to use c-tor injection you can use property injection instead. If you don't want to inject the value all the type, then use a When(..) condition to specify when to inject and when not to. Combine this with the null-object pattern to keep ninject from complaining that it can't inject a requested type.
Property Injection
Adapt a worker as follows:
public class WorkerA
{
[Inject]
public BrowserTabId BrowserTabId { get; set; }
....
}
Note, however, for this to work, like normal constructor injection, it is necessary that either the WorkerA is instanciated by ninject or that Ninject is informed about its existence by Ninject.Inject(workerAInstance)
Scoping
Since you mention that the lifetime of the ID in your actual application is somewhat more complicated, I guess you will have to use something different than InRequestScope - maybe roll your own scope (by using InScope(...)). Or Maybe, InCallScope() is as viable alternative. However, without knowing what exactly it is what you need, it's a bit difficult to advise you properly.
I've been reading about TDD and I've seen a lot of posts about not to do any database transaction because "single, isolated block of code with no dependencies".
So now I have a little bit of dilemma - I want to be able to test if my service layer method called AddNewStudent actually works. This method goes into my DbContext and then add a new record into the database. If database operations aren't recommended for TDD then how else can I test AddNewStudent method aside from just testing my application on a browser?
public class StudentManager : ManagerBase
{
internal StudentManager() { }
public Student AddNewStudent(string fName, string lName, DateTime dob)
{
// Create a student model instance using factory
var record = Factories.StudentFac.CreateOne(fName, lName, dob);
DbContext.Students.Add(record);
DbContext.SaveChanges();
return record;
}
}
And my test looks like this
[TestMethod]
public void StudentManager_AddNewStudent_Test()
{
var fName = "Ryan";
var lName = "Rigil";
var dob = DateTime.Parse("3/1/2006");
var student = Managers.StudentManager.AddNewStudent(fName, lName, dob);
Assert.AreEqual(fName, student.FirstName);
Assert.AreEqual(lName, student.LastName);
Assert.AreEqual(dob.ToShortDateString(), student.DoB.ToShortDateString());
}
Your StudentManager has dependencies buried internally that make it difficult to test. Consider restructuring your design to allow for better testability.
Looking at the StudentManager the following assumptions were derived...
//An assumed abstraction of the ManagerBase
public abstract class ManagerBase {
public ManagerBase(IDbContext dbContext, IFactory factories) {
DbContext = dbContext;
Factories = factories;
}
public IDbContext DbContext { get; private set; }
public IFactory Factories { get; private set; }
}
//An abstraction of what the unit of work would look like
public interface IDbContext {
//student repository
DbSet<Student> Students { get; }
//...other repositories
int SaveChanges();
}
//Just an example of the Student Factory.
public interface IModelFactory<T> where T : class, new() {
T Create(Action<T> configuration);
}
public interface IFactory {
IModelFactory<Student> StudentFac { get; }
//...other factories. Should try to make your factories Generic
}
With that the target class refactors to...
public class StudentManager : ManagerBase {
public StudentManager(IDbContext dbContext, IFactory factories) : base(dbContext, factories) { }
public Student AddNewStudent(string fName, string lName, DateTime dob) {
// Create a student model instance using factory
var record = Factories.StudentFac.Create(r => {
r.FirstName = fName;
r.LastName = lName;
r.DoB = dob;
});
base.DbContext.Students.Add(record);
base.DbContext.SaveChanges();
return record;
}
}
While it may look like much it will greatly help the testability of your code.
A mocking framework like Moq can now be used to create a fake version of the database access and factories...
[TestMethod]
public void StudentManager_Should_AddNewStudent() {
//Arrange: setup/initialize the dependencies of the test
var fName = "Ryan";
var lName = "Rigil";
var dob = DateTime.Parse("3006-01-03");
//using Moq to create mocks/fake of dependencies
var dbContextMock = new Mock<IDbContext>();
//Extension method used to create a mock of DbSet<T>
var dbSetMock = new List<Student>().AsDbSetMock();
dbContextMock.Setup(x => x.Students).Returns(dbSetMock.Object);
var factoryMock = new Mock<IFactory>();
factoryMock
.Setup(x => x.StudentFac.Create(It.IsAny<Action<Student>>()))
.Returns<Action<Student>>(a => {
var s = new Student();
a(s);
return s;
});
//this is the system/class under test.
//while this is being created manually, you should look into
//using DI/IoC container to manage Dependency Injection
var studentManager = new StudentManager(dbContextMock.Object, factoryMock.Object);
//Act: here we actually test the method
var student = studentManager.AddNewStudent(fName, lName, dob);
//Assert: and check that it executed as expected
Assert.AreEqual(fName, student.FirstName);
Assert.AreEqual(lName, student.LastName);
Assert.AreEqual(dob.ToShortDateString(), student.DoB.ToShortDateString());
}
For production you can create proper implementations of the interfaces and inject them into the classes that depend on them. This answer is based entirely on the example you provided in your post. Take some time to understand the concepts used and also do some more research online. You can then apply these concepts with the remainder of your project as you progress with TDD.
I have a class with a method that returns an object of type User
public class CustomMembershipProvider : MembershipProvider
{
public virtual User GetUser(string username, string password, string email, bool isApproved)
{
return new User()
{
Name = username
,Password = EncodePassword(password)
,Email = email
,Status = (isApproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente)
// ...
};
}
// ..
}
User is a domain object. Note the Id property with setter as protected:
public class User : IAuditable, IUser
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual string Email { get; set; }
public virtual UsuarioStatusEnum Status { get; set; }
public virtual string Password { get; set; }
}
Id is protected because it is generated by the database.
Test project
In my Test project I have a Fake repository with a method Store to save/update the object:
public void Store(T obj)
{
if (obj.Id > 0)
_context[obj.Id] = obj;
else
{
var generateId = _context.Values.Any() ? _context.Values.Max(p => p.Id) + 1 : 1;
var stubUser = Mock.Get<T>(obj); // In test, will always mock
stubUser.Setup(s => s.Id).Returns(generateId);
_context.Add(generateId, stubUser.Object);
}
}
In CustomMembershipProvider I have public override MembershipUser CreateUser method that calls the GetUser to create a User.
This way, all I have to do is mock the GetUser method so that the repository can generate the Id
var membershipMoq = new Mock<CustomMembershipProvider>();
membershipMoq.CallBase = true;
membershipMoq
.Setup(p => p.GetUser(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Returns<string, string, string, bool>( (username, password, email, isAproved) => {
var moqUser = new Mock<User>();
moqUser.Object.Name = username;
moqUser.Object.Password = password;
moqUser.Object.Email = email;
moqUser.Object.Status = (isAproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente);
return moqUser.Object;
});
_membershipProvider = membershipMoq.Object;
Problem
In theory everything is correct. When CreateUser call 'GetUser' to create a user, the user will return Mock filled;
[TestMethod]
public void CreateUser_deve_criar_usuario_no_repositorio()
{
// Act
MembershipCreateStatus status;
var usr = _membershipProvider.CreateUser(
_fixture.Create<string>(),
_fixture.Create<string>(),
_fixture.Create<string>(),
null, null, true, null,
out status);
// usr should have name, email password filled. But not!
// Assert
status.Should().Be(MembershipCreateStatus.Success);
}
The problem is that Email, Name, Password are empty (with default values)!
The way you prepare the mocked user is the problem.
moqUser.Object.Name = username;
will not set the name, unless you have setup the mock properly.
Try this before assigning values to properties:
moqUser.SetupAllProperties();
This method will prepare all properties on the mock to be able to record the assigned value, and replay it later (i.e. to act as real property).
You can also use SetupProperty() method to set up individual properties to be able to record the passed in value.
Another approach is:
var mockUser = Mock.Of<User>( m =>
m.Name == "whatever" &&
m.Email == "someone#example.com");
return mockUser;
I think you are missing purpose of mocking. Mocks used to mock dependencies of class you are testing:
System under test (SUT) should be tested in isolation (i.e. separate from other units). Otherwise errors in dependencies will cause your SUTs tests to fail. Also you should not write tests for mocks. That gives you nothing, because mocks are not production code. Mocks are not executed in your application.
So, you should mock CustomMembershipProvider only if you are testing some unit, which depends on it (BTW it's better to create some abstraction like interface ICustomMembershipProvider to depend on).
Or, if you are writing tests for CustomMembershipProvider class, then it should not be mocked - only dependencies of this provider should be mocked.
Specifies that the all properties on the mock should have "property behavior",
meaning that setting their value will cause them to be saved and later returned when the properties is requested.
(This is also known as "stubbing".)
The default value for each property will be the one generated as specified by the
property for the mock.
mock.SetupAllProperties();